Updated copyright notices to show "2004"
[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 <kasper@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 * 416: function cleanUpQueryConfig($queryConfig)
46 * 473: function getFormElements($subLevel=0,$queryConfig="",$parent="")
47 * 560: function printCodeArray($codeArr,$l=0)
48 * 583: function formatQ($str)
49 * 596: function mkOperatorSelect($name,$op,$draw,$submit)
50 * 618: function mkTypeSelect($name,$fieldName,$prepend="FIELD_")
51 * 637: function verifyType($fieldName)
52 * 654: function verifyComparison($comparison,$neg)
53 * 673: function mkFieldToInputSelect($name,$fieldName)
54 * 694: function mkTableSelect($name,$cur)
55 * 716: function mkCompSelect($name,$comparison,$neg)
56 * 734: function getSubscript($arr)
57 * 749: function initUserDef()
58 * 758: function userDef()
59 * 767: function userDefCleanUp($queryConfig)
60 * 778: function getQuery ($queryConfig,$pad="")
61 * 808: function getQuerySingle($conf,$first)
62 * 829: function cleanInputVal($conf,$suffix="")
63 * 848: function getUserDefQuery ($qcArr)
64 * 856: function updateIcon()
65 * 865: function getLabelCol()
66 * 877: function makeSelectorTable($modSettings,$enableList="table,fields,query,group,order,limit")
67 * 981: function getSelectQuery($qString="")
68 * 1005: function JSbottom($formname="forms[0]")
69 * 1011: function typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue)
70 * 1029: 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 <kasper@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"] = stripslashes(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 t3lib_div::stripSlashesOnArray($this->queryConfig);
311
312 /* // adjust queryConfig to match requests from user
313 if($GLOBALS["HTTP_POST_VARS"]["queryConfig"]) {
314 $this->queryConfig = $GLOBALS["HTTP_POST_VARS"]["queryConfig"];
315 t3lib_div::stripSlashesOnArray($this->queryConfig);
316 }
317 */
318 // if delete...
319 if($GLOBALS["HTTP_POST_VARS"]["qG_del"]) {
320 //initialize array to work on, save special parameters
321 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_del"]);
322 $workArr =& $this->queryConfig;
323 for($i=0;$i<sizeof($ssArr)-1;$i++) {
324 $workArr =& $workArr[$ssArr[$i]];
325 }
326 // delete the entry and move the other entries
327 unset($workArr[$ssArr[$i]]);
328 for($j=$ssArr[$i];$j<sizeof($workArr);$j++) {
329 $workArr[$j] = $workArr[$j+1];
330 unset($workArr[$j+1]);
331 }
332 }
333
334 // if insert...
335 if($GLOBALS["HTTP_POST_VARS"]["qG_ins"]) {
336 //initialize array to work on, save special parameters
337 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_ins"]);
338 $workArr =& $this->queryConfig;
339 for($i=0;$i<sizeof($ssArr)-1;$i++) {
340 $workArr =& $workArr[$ssArr[$i]];
341 }
342 // move all entries above position where new entry is to be inserted
343 for($j=sizeof($workArr);$j>$ssArr[$i];$j--) {
344 $workArr[$j] = $workArr[$j-1];
345 }
346 //clear new entry position
347 unset($workArr[$ssArr[$i]+1]);
348 $workArr[$ssArr[$i]+1]['type'] = "FIELD_";
349 }
350
351 // if move up...
352 if($GLOBALS["HTTP_POST_VARS"]["qG_up"]) {
353 //initialize array to work on
354 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_up"]);
355 $workArr =& $this->queryConfig;
356 for($i=0;$i<sizeof($ssArr)-1;$i++) {
357 $workArr =& $workArr[$ssArr[$i]];
358 }
359 //swap entries
360 $qG_tmp = $workArr[$ssArr[$i]];
361 $workArr[$ssArr[$i]] = $workArr[$ssArr[$i]-1];
362 $workArr[$ssArr[$i]-1] = $qG_tmp;
363 }
364
365 // if new level...
366 if($GLOBALS["HTTP_POST_VARS"]["qG_nl"]) {
367 //initialize array to work on
368 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_nl"]);
369 $workArr =& $this->queryConfig;
370 for($i=0;$i<sizeof($ssArr)-1;$i++) {
371 $workArr =& $workArr[$ssArr[$i]];
372 }
373 // Do stuff:
374 $tempEl = $workArr[$ssArr[$i]];
375 if (is_array($tempEl)) {
376 if ($tempEl["type"]!="newlevel") {
377 $workArr[$ssArr[$i]]=array(
378 "type" => "newlevel",
379 "operator" => $tempEl["operator"],
380 "nl" => array($tempEl)
381 );
382 }
383 }
384 }
385
386 // if collapse level...
387 if($GLOBALS["HTTP_POST_VARS"]["qG_remnl"]) {
388 //initialize array to work on
389 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_remnl"]);
390 $workArr =& $this->queryConfig;
391 for($i=0;$i<sizeof($ssArr)-1;$i++) {
392 $workArr =& $workArr[$ssArr[$i]];
393 }
394
395 // Do stuff:
396 $tempEl = $workArr[$ssArr[$i]];
397 if (is_array($tempEl)) {
398 if ($tempEl["type"]=="newlevel") {
399 $a1 = array_slice($workArr,0,$ssArr[$i]);
400 $a2 = array_slice($workArr,$ssArr[$i]);
401 array_shift($a2);
402 $a3 = $tempEl["nl"];
403 $a3[0]["operator"] = $tempEl["operator"];
404 $workArr=array_merge($a1,$a3,$a2);
405 }
406 }
407 }
408 }
409
410 /**
411 * [Describe function...]
412 *
413 * @param [type] $queryConfig: ...
414 * @return [type] ...
415 */
416 function cleanUpQueryConfig($queryConfig) {
417 //since we dont traverse the array using numeric keys in the upcoming whileloop make sure it's fresh and clean before displaying
418 if (is_array($queryConfig)) {
419 ksort($queryConfig);
420 } else {
421 //queryConfig should never be empty!
422 if(!$queryConfig[0] || !$queryConfig[0]["type"]) $queryConfig[0] = array("type"=>"FIELD_");
423 }
424 // Traverse:
425 reset($queryConfig);
426 $c=0;
427 $arrCount=0;
428 while(list($key,$conf)=each($queryConfig)) {
429 if(substr($conf["type"],0,6)=="FIELD_") {
430 $fName = substr($conf["type"],6);
431 $fType = $this->fields[$fName]["type"];
432 } elseif($conf["type"]=="newlevel") {
433 $fType = $conf["type"];
434 } else {
435 $fType = "ignore";
436 }
437 // debug($fType);
438 switch($fType) {
439 case "newlevel":
440 if(!$queryConfig[$key]["nl"]) $queryConfig[$key]["nl"][0]["type"] = "FIELD_";
441 $queryConfig[$key]["nl"]=$this->cleanUpQueryConfig($queryConfig[$key]["nl"]);
442 break;
443 case "userdef":
444 $queryConfig[$key]=$this->userDefCleanUp($queryConfig[$key]);
445 break;
446 case "ignore":
447 default:
448 // debug($queryConfig[$key]);
449 $verifiedName=$this->verifyType($fName);
450 $queryConfig[$key]["type"]="FIELD_".$this->verifyType($verifiedName);
451
452 if($conf["comparison"] >> 5 != $this->comp_offsets[$fType]) $conf["comparison"] = $this->comp_offsets[$fType] << 5;
453 $queryConfig[$key]["comparison"]=$this->verifyComparison($conf["comparison"],$conf["negate"]?1:0);
454
455 $queryConfig[$key]["inputValue"]=stripslashes($this->cleanInputVal($queryConfig[$key]));
456 $queryConfig[$key]["inputValue1"]=stripslashes($this->cleanInputVal($queryConfig[$key],1));
457
458 // debug($queryConfig[$key]);
459 break;
460 }
461 }
462 return $queryConfig;
463 }
464
465 /**
466 * [Describe function...]
467 *
468 * @param [type] $subLevel: ...
469 * @param [type] $queryConfig: ...
470 * @param [type] $parent: ...
471 * @return [type] ...
472 */
473 function getFormElements($subLevel=0,$queryConfig="",$parent="") {
474 $codeArr=array();
475 if (!is_array($queryConfig)) $queryConfig=$this->queryConfig;
476
477 reset($queryConfig);
478 $c=0;
479 $arrCount=0;
480 while(list($key,$conf)=each($queryConfig)) {
481 $subscript = $parent."[$key]";
482 $lineHTML = "";
483 $lineHTML.=$this->mkOperatorSelect($this->name.$subscript,$conf["operator"],$c,($conf["type"]!="FIELD_"));
484 if(substr($conf["type"],0,6)=="FIELD_") {
485 $fName = substr($conf["type"],6);
486 $fType = $this->fields[$fName]["type"];
487 if($conf["comparison"] >> 5 != $this->comp_offsets[$fType]) $conf["comparison"] = $this->comp_offsets[$fType] << 5;
488
489 //nasty nasty...
490 //make sure queryConfig contains _actual_ comparevalue.
491 //mkCompSelect don't care, but getQuery does.
492 $queryConfig[$key]["comparison"] += (isset($conf["negate"])-($conf["comparison"]%2));
493
494 } elseif($conf["type"]=="newlevel") {
495 $fType = $conf["type"];
496 } else {
497 $fType = "ignore";
498 }
499 // debug($fType);
500 switch($fType) {
501 case "ignore":
502 break;
503 case "newlevel":
504 if(!$queryConfig[$key]["nl"]) $queryConfig[$key]["nl"][0]["type"] = "FIELD_";
505 $lineHTML.='<input type="hidden" name="'.$this->name.$subscript.'[type]" value="newlevel">';
506 $codeArr[$arrCount]["sub"] = $this->getFormElements($subLevel+1,$queryConfig[$key]["nl"],$subscript."[nl]");
507 break;
508 case "userdef":
509 $lineHTML.=$this->userDef($this->name.$subscript,$conf,$fName,$fType);
510 break;
511 default:
512 $lineHTML.=$this->mkTypeSelect($this->name.$subscript.'[type]',$fName);
513 $lineHTML.=$this->mkCompSelect($this->name.$subscript.'[comparison]',$conf["comparison"],$conf["negate"]?1:0);
514 $lineHTML.='<input type="checkbox" '.($conf["negate"]?"checked":"").' name="'.$this->name.$subscript.'[negate]'.'" onClick="submit();">';
515
516 if ($conf["comparison"]==37 || $conf["comparison"]==36) { // between:
517 $lineHTML.='<input type="text" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(5).'>
518 <input type="text" value="'.htmlspecialchars($conf["inputValue1"]).'" name="'.$this->name.$subscript.'[inputValue1]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(5).'>
519 '; // onChange="submit();"
520 } elseif ($fType=="date") {
521 $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]'.'">';
522 $this->extJSCODE.='typo3FormFieldSet("'.$this->name.$subscript.'[inputValue]", "datetime", "", 0,0);';
523 } else {
524 $lineHTML.='<input type="text" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).'>'; // onChange="submit();"
525 }
526 break;
527 }
528 if($fType != "ignore") {
529 $lineHTML .= $this->updateIcon();
530 $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.'">';
531 $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.'">';
532 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.'">';
533
534 if($c!=0 && $fType!="newlevel") {
535 $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.'">';
536 }
537 if($fType=="newlevel") {
538 $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.'">';
539 }
540
541 $codeArr[$arrCount]["html"] = $lineHTML;
542 $codeArr[$arrCount]["query"] = $this->getQuerySingle($conf,$c>0?0:1);
543 $arrCount++;
544 $c++;
545 }
546 }
547 // $codeArr[$arrCount] .='<input type="hidden" name="CMD" value="displayQuery">';
548 $this->queryConfig = $queryConfig;
549 //modifyHTMLColor($color,$R,$G,$B)
550 return $codeArr;
551 }
552
553 /**
554 * [Describe function...]
555 *
556 * @param [type] $codeArr: ...
557 * @param [type] $l: ...
558 * @return [type] ...
559 */
560 function printCodeArray($codeArr,$l=0) {
561 reset($codeArr);
562 $line="";
563 if ($l) $indent='<td><img height="1" width="50"></td>';
564 $lf=$l*30;
565 $bgColor = t3lib_div::modifyHTMLColor($GLOBALS["TBE_TEMPLATE"]->bgColor2,$lf,$lf,$lf);
566 while(list($k,$v)=each($codeArr)) {
567 $line.= '<tr>'.$indent.'<td bgcolor="'.$bgColor.'"'.$this->noWrap.'>'.$v["html"].'</td></tr>';
568 if ($this->enableQueryParts) {$line.= '<tr>'.$indent.'<td>'.$this->formatQ($v["query"]).'</td></tr>';}
569 if (is_array($v["sub"])) {
570 $line.= '<tr>'.$indent.'<td'.$this->noWrap.'>'.$this->printCodeArray($v["sub"],$l+1).'</td></tr>';
571 }
572 }
573 $out='<table border=0 cellpadding=0 cellspacing=1>'.$line.'</table>';
574 return $out;
575 }
576
577 /**
578 * [Describe function...]
579 *
580 * @param [type] $str: ...
581 * @return [type] ...
582 */
583 function formatQ($str) {
584 return '<font size=1 face=verdana color=maroon><i>'.$str.'</i></font>';
585 }
586
587 /**
588 * [Describe function...]
589 *
590 * @param [type] $name: ...
591 * @param [type] $op: ...
592 * @param [type] $draw: ...
593 * @param [type] $submit: ...
594 * @return [type] ...
595 */
596 function mkOperatorSelect($name,$op,$draw,$submit) {
597 if ($draw) {
598 $out='<select name="'.$name.'[operator]"'.($submit?' onChange="submit();"':'').'>'; //
599 $out.='<option value="AND"'.(!$op||$op=="AND" ? ' selected':'').'>'.$this->lang["AND"].'</option>';
600 $out.='<option value="OR"'.($op=="OR" ? ' selected':'').'>'.$this->lang["OR"].'</option>';
601 $out.='</select>';
602 } else {
603 $out.='<input type="hidden" value="'.$op.'" name="'.$name.'[operator]">';
604 $out.='<img src="clear.gif" height="1" width="47">';
605
606 }
607 return $out;
608 }
609
610 /**
611 * [Describe function...]
612 *
613 * @param [type] $name: ...
614 * @param [type] $fieldName: ...
615 * @param [type] $prepend: ...
616 * @return [type] ...
617 */
618 function mkTypeSelect($name,$fieldName,$prepend="FIELD_") {
619 $out='<select name="'.$name.'" onChange="submit();">';
620 $out.='<option value=""></option>';
621 reset($this->fields);
622 while(list($key,)=each($this->fields)) {
623 if ($GLOBALS["BE_USER"]->check("non_exclude_fields",$this->table.":".$key)) {
624 $out.='<option value="'.$prepend.$key.'"'.($key==$fieldName ? ' selected':'').'>'.$this->fields[$key]["label"].'</option>';
625 }
626 }
627 $out.='</select>';
628 return $out;
629 }
630
631 /**
632 * [Describe function...]
633 *
634 * @param [type] $fieldName: ...
635 * @return [type] ...
636 */
637 function verifyType($fieldName) {
638 reset($this->fields);
639 $first = "";
640 while(list($key,)=each($this->fields)) {
641 if (!$first) $first = $key;
642 if ($key==$fieldName) return $key;
643 }
644 return $first;
645 }
646
647 /**
648 * [Describe function...]
649 *
650 * @param [type] $comparison: ...
651 * @param [type] $neg: ...
652 * @return [type] ...
653 */
654 function verifyComparison($comparison,$neg) {
655 $compOffSet = $comparison >> 5;
656 $first=-1;
657 for($i=32*$compOffSet+$neg;$i<32*($compOffSet+1);$i+=2) {
658 if ($first==-1) $first = $i;
659 if (($i >> 1)==($comparison >> 1)) {
660 return $i;
661 }
662 }
663 return $first;
664 }
665
666 /**
667 * [Describe function...]
668 *
669 * @param [type] $name: ...
670 * @param [type] $fieldName: ...
671 * @return [type] ...
672 */
673 function mkFieldToInputSelect($name,$fieldName) {
674 $out='<input type="Text" value="'.htmlspecialchars($fieldName).'" name="'.$name.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth().'>'.$this->updateIcon();
675 $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>';
676 $out.='<BR><select name="_fieldListDummy" size=5 onChange="document.forms[0][\''.$name.'\'].value+=\',\'+this.value">';
677 reset($this->fields);
678 while(list($key,)=each($this->fields)) {
679 if ($GLOBALS["BE_USER"]->check("non_exclude_fields",$this->table.":".$key)) {
680 $out.='<option value="'.$prepend.$key.'"'.($key==$fieldName ? ' selected':'').'>'.$this->fields[$key]["label"].'</option>';
681 }
682 }
683 $out.='</select>';
684 return $out;
685 }
686
687 /**
688 * [Describe function...]
689 *
690 * @param [type] $name: ...
691 * @param [type] $cur: ...
692 * @return [type] ...
693 */
694 function mkTableSelect($name,$cur) {
695 global $TCA;
696 $out='<select name="'.$name.'" onChange="submit();">';
697 $out.='<option value=""></option>';
698 reset($TCA);
699 while(list($tN)=each($TCA)) {
700 if ($GLOBALS["BE_USER"]->check("tables_select",$tN)) {
701 $out.='<option value="'.$tN.'"'.($tN==$cur ? ' selected':'').'>'.$GLOBALS["LANG"]->sl($TCA[$tN]["ctrl"]["title"]).'</option>';
702 }
703 }
704 $out.='</select>';
705 return $out;
706 }
707
708 /**
709 * [Describe function...]
710 *
711 * @param [type] $name: ...
712 * @param [type] $comparison: ...
713 * @param [type] $neg: ...
714 * @return [type] ...
715 */
716 function mkCompSelect($name,$comparison,$neg) {
717 $compOffSet = $comparison >> 5;
718 $out='<select name="'.$name.'" onChange="submit();">';
719 for($i=32*$compOffSet+$neg;$i<32*($compOffSet+1);$i+=2) {
720 if($this->lang["comparison"][$i."_"]) {
721 $out.='<option value="'.$i.'"'.(($i >> 1)==($comparison >> 1) ? ' selected':'').'>'.$this->lang["comparison"][$i."_"].'</option>';
722 }
723 }
724 $out.='</select>';
725 return $out;
726 }
727
728 /**
729 * [Describe function...]
730 *
731 * @param [type] $arr: ...
732 * @return [type] ...
733 */
734 function getSubscript($arr) {
735 while(is_array($arr)) {
736 reset($arr);
737 list($key,)=each($arr);
738 $retArr[] = $key;
739 $arr = $arr[$key];
740 }
741 return $retArr;
742 }
743
744 /**
745 * [Describe function...]
746 *
747 * @return [type] ...
748 */
749 function initUserDef() {
750
751 }
752
753 /**
754 * [Describe function...]
755 *
756 * @return [type] ...
757 */
758 function userDef() {
759 }
760
761 /**
762 * [Describe function...]
763 *
764 * @param [type] $queryConfig: ...
765 * @return [type] ...
766 */
767 function userDefCleanUp($queryConfig) {
768 return $queryConfig;
769 }
770
771 /**
772 * [Describe function...]
773 *
774 * @param [type] $queryConfig: ...
775 * @param [type] $pad: ...
776 * @return [type] ...
777 */
778 function getQuery ($queryConfig,$pad="") {
779 $qs = "";
780 //since wo dont traverse the array using numeric keys in the upcoming whileloop make sure it's fresh and clean
781 ksort($queryConfig);
782 reset($queryConfig);
783 $first=1;
784 while(list($key,$conf) = each($queryConfig)) {
785 switch($conf["type"]) {
786 case "newlevel":
787 $qs.=chr(10).$pad.trim($conf["operator"])." (".$this->getQuery($queryConfig[$key]["nl"],$pad." ").chr(10).$pad.")";
788 break;
789 case "userdef":
790 $qs.=chr(10).$pad.getUserDefQuery($conf,$first);
791 break;
792 default:
793 $qs.=chr(10).$pad.$this->getQuerySingle($conf,$first);
794 break;
795 }
796 $first=0;
797 }
798 return $qs;
799 }
800
801 /**
802 * [Describe function...]
803 *
804 * @param [type] $conf: ...
805 * @param [type] $first: ...
806 * @return [type] ...
807 */
808 function getQuerySingle($conf,$first) {
809 $prefix = $this->enablePrefix ? $this->table."." : "";
810 if (!$first) {$qs.= trim(($conf["operator"]?$conf["operator"]:"AND"))." ";} // Is it OK to insert the AND operator if none is set?
811 $qsTmp = str_replace("#FIELD#",$prefix.trim(substr($conf["type"],6)),$this->compSQL[$conf["comparison"]]);
812 $inputVal = $this->cleanInputVal($conf);
813 $qsTmp = str_replace("#VALUE#",$inputVal,$qsTmp);
814 if ($conf["comparison"]==37 || $conf["comparison"]==36) { // between:
815 $inputVal = $this->cleanInputVal($conf,"1");
816 $qsTmp = str_replace("#VALUE1#",$inputVal,$qsTmp);
817 }
818 $qs .= trim($qsTmp);
819 return $qs;
820 }
821
822 /**
823 * [Describe function...]
824 *
825 * @param [type] $conf: ...
826 * @param [type] $suffix: ...
827 * @return [type] ...
828 */
829 function cleanInputVal($conf,$suffix="") {
830 if(($conf["comparison"] >> 5==0) || ($conf["comparison"]==32 || $conf["comparison"]==33)) {
831 $inputVal = addslashes($conf["inputValue".$suffix]);
832 } else {
833 if ($conf["comparison"]==39 || $conf["comparison"]==38) { // in list:
834 $inputVal = implode(",",t3lib_div::intExplode(",",$conf["inputValue".$suffix]));
835 } else {
836 $inputVal = doubleval($conf["inputValue".$suffix]);
837 }
838 }
839 return $inputVal;
840 }
841
842 /**
843 * [Describe function...]
844 *
845 * @param [type] $qcArr: ...
846 * @return [type] ...
847 */
848 function getUserDefQuery ($qcArr) {
849 }
850
851 /**
852 * [Describe function...]
853 *
854 * @return [type] ...
855 */
856 function updateIcon() {
857 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">';
858 }
859
860 /**
861 * [Describe function...]
862 *
863 * @return [type] ...
864 */
865 function getLabelCol() {
866 global $TCA;
867 return $TCA[$this->table]["ctrl"]["label"];
868 }
869
870 /**
871 * [Describe function...]
872 *
873 * @param [type] $modSettings: ...
874 * @param [type] $enableList: ...
875 * @return [type] ...
876 */
877 function makeSelectorTable($modSettings,$enableList="table,fields,query,group,order,limit") {
878 $enableArr=explode(",",$enableList);
879 // Make output
880 $TDparams = ' class="bgColor5" nowrap';
881
882 if (in_array("table",$enableArr)) {
883 $out='
884 <tr>
885 <td'.$TDparams.'><strong>Select a table:</strong></td>
886 <td'.$TDparams.'>'.$this->mkTableSelect("SET[queryTable]",$this->table).'</td>
887 </tr>';
888 }
889 if ($this->table) {
890
891 // Init fields:
892 $this->setAndCleanUpExternalLists("queryFields",$modSettings["queryFields"],"uid,".$this->getLabelCol());
893 $this->setAndCleanUpExternalLists("queryGroup",$modSettings["queryGroup"]);
894 $this->setAndCleanUpExternalLists("queryOrder",$modSettings["queryOrder"].",".$modSettings["queryOrder2"]);
895
896 // Limit:
897 $this->extFieldLists["queryLimit"]=$modSettings["queryLimit"];
898 if (!$this->extFieldLists["queryLimit"]) $this->extFieldLists["queryLimit"]=100;
899 $parts = t3lib_div::intExplode(",",$this->extFieldLists["queryLimit"]);
900 $this->extFieldLists["queryLimit"] = implode(",",array_slice($parts,0,2));
901
902 // Insert Descending parts
903 if ($this->extFieldLists["queryOrder"]) {
904 $descParts = explode(",",$modSettings["queryOrderDesc"].",".$modSettings["queryOrder2Desc"]);
905 $orderParts = explode(",",$this->extFieldLists["queryOrder"]);
906 reset($orderParts);
907 $reList=array();
908 while(list($kk,$vv)=each($orderParts)) {
909 $reList[]=$vv.($descParts[$kk]?" DESC":"");
910 }
911 $this->extFieldLists["queryOrder_SQL"] = implode(",",$reList);
912 }
913
914 // Query Generator:
915 $this->procesData($modSettings["queryConfig"] ? unserialize($modSettings["queryConfig"]) : "");
916 // debug($this->queryConfig);
917 $this->queryConfig = $this->cleanUpQueryConfig($this->queryConfig);
918 // debug($this->queryConfig);
919 $this->enableQueryParts = $modSettings["search_query_smallparts"];
920
921 $codeArr=$this->getFormElements();
922 $queryCode=$this->printCodeArray($codeArr);
923
924 if (in_array("fields",$enableArr)) {
925 $out.='
926 <tr>
927 <td'.$TDparams.'><strong>Select fields:</strong></td>
928 <td'.$TDparams.'>'.$this->mkFieldToInputSelect("SET[queryFields]",$this->extFieldLists["queryFields"]).'</td>
929 </tr>';
930 }
931 if (in_array("query",$enableArr)) {
932 $out.='<tr>
933 <td colspan=2'.$TDparams.'><strong>Make Query:</strong></td>
934 </tr>
935 <tr>
936 <td colspan=2>'.$queryCode.'</td>
937 </tr>
938 ';
939 }
940 if (in_array("group",$enableArr)) {
941 $out.='<tr>
942 <td'.$TDparams.'><strong>Group By:</strong></td>
943 <td'.$TDparams.'>'.$this->mkTypeSelect("SET[queryGroup]",$this->extFieldLists["queryGroup"],"").'</td>
944 </tr>';
945 }
946 if (in_array("order",$enableArr)) {
947 $orderByArr = explode(",",$this->extFieldLists["queryOrder"]);
948 // debug($orderByArr);
949 $orderBy="";
950 $orderBy.=$this->mkTypeSelect("SET[queryOrder]",$orderByArr[0],"").
951 "&nbsp;".t3lib_BEfunc::getFuncCheck($GLOBALS["SOBE"]->id,"SET[queryOrderDesc]",$modSettings["queryOrderDesc"])."&nbsp;Descending";
952 if ($orderByArr[0]) {
953 $orderBy.= "<BR>".$this->mkTypeSelect("SET[queryOrder2]",$orderByArr[1],"").
954 "&nbsp;".t3lib_BEfunc::getFuncCheck($GLOBALS["SOBE"]->id,"SET[queryOrder2Desc]",$modSettings["queryOrder2Desc"])."&nbsp;Descending";
955 }
956 $out.='<tr>
957 <td'.$TDparams.'><strong>Order By:</strong></td>
958 <td'.$TDparams.'>'.$orderBy.'</td>
959 </tr>';
960 }
961 if (in_array("limit",$enableArr)) {
962 $limit = '<input type="Text" value="'.htmlspecialchars($this->extFieldLists["queryLimit"]).'" name="SET[queryLimit]"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).'>'.$this->updateIcon();
963 $out.='<tr>
964 <td'.$TDparams.'><strong>Limit:</strong></td>
965 <td'.$TDparams.'>'.$limit.'</td>
966 </tr>
967 ';
968 }
969 }
970 $out='<table border=0 cellpadding=3 cellspacing=1>'.$out.'</table>';
971 $out.=$this->JSbottom();
972 return $out;
973 }
974
975 /**
976 * [Describe function...]
977 *
978 * @param [type] $qString: ...
979 * @return [type] ...
980 */
981 function getSelectQuery($qString="") {
982 if (!$qString) $qString=$this->getQuery($this->queryConfig);
983
984 $query = "SELECT ".$this->extFieldLists["queryFields"]."
985 FROM ".$this->table."
986 WHERE ".$qString."
987 ".t3lib_BEfunc::deleteClause($this->table);
988
989 if ($this->extFieldLists["queryGroup"]) {
990 $query.=chr(10)."GROUP BY ".$this->extFieldLists["queryGroup"];
991 }
992 if ($this->extFieldLists["queryOrder"]) {
993 $query.=chr(10)."ORDER BY ".$this->extFieldLists["queryOrder_SQL"];
994 }
995 $query.=chr(10)."LIMIT ".$this->extFieldLists["queryLimit"];
996 return $query;
997 }
998
999 /**
1000 * [Describe function...]
1001 *
1002 * @param [type] $formname: ...
1003 * @return [type] ...
1004 */
1005 function JSbottom($formname="forms[0]") {
1006 if ($this->extJSCODE) {
1007 $out.='
1008 <script language="javascript" type="text/javascript" src="'.$GLOBALS["BACK_PATH"].'t3lib/jsfunc.evalfield.js"></script>
1009 <script language="javascript" type="text/javascript">
1010 var evalFunc = new evalFunc;
1011 function typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue) {
1012 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
1013 var theValue = document.'.$formname.'[theField].value;
1014 if (checkbox && theValue==checkboxValue) {
1015 document.'.$formname.'[theField+"_hr"].value="";
1016 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "";
1017 } else {
1018 document.'.$formname.'[theField+"_hr"].value = evalFunc.outputObjValue(theFObj, theValue);
1019 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "on";
1020 }
1021 }
1022
1023 /**
1024 * [Describe function...]
1025 *
1026 * @param [type] $theField, evallist, is_in, checkbox, checkboxValue, checkbox_off: ...
1027 * @return [type] ...
1028 */
1029 function typo3FormFieldGet(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off) {
1030 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
1031 if (checkbox_off) {
1032 document.'.$formname.'[theField].value=checkboxValue;
1033 }else{
1034 document.'.$formname.'[theField].value = evalFunc.evalObjValue(theFObj, document.'.$formname.'[theField+"_hr"].value);
1035 }
1036 typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue);
1037 }
1038 </script>
1039 <script language="javascript" type="text/javascript">'.$this->extJSCODE.'</script>';
1040 return $out;
1041 }
1042 }
1043 }
1044
1045
1046 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_querygenerator.php']) {
1047 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_querygenerator.php']);
1048 }
1049 ?>