* Changed quotes in 3 files. Cleanup + needed by an upcoming patch.
[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 we don't 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) {
806 // Is it OK to insert the AND operator if none is set?
807 $qs .= trim(($conf['operator'] ? $conf['operator'] : 'AND')).' ';
808 }
809 $qsTmp = str_replace('#FIELD#', $prefix.trim(substr($conf['type'],6)), $this->compSQL[$conf['comparison']]);
810 $inputVal = $this->cleanInputVal($conf);
811 $qsTmp = str_replace('#VALUE#', $GLOBALS['TYPO3_DB']->quoteStr($inputVal,$this->table), $qsTmp);
812 if ($conf['comparison']==37 || $conf['comparison']==36) { // between:
813 $inputVal = $this->cleanInputVal($conf,'1');
814 $qsTmp = str_replace('#VALUE1#', $GLOBALS['TYPO3_DB']->quoteStr($inputVal,$this->table), $qsTmp);
815 }
816 $qs .= trim($qsTmp);
817 return $qs;
818 }
819
820 /**
821 * [Describe function...]
822 *
823 * @param [type] $conf: ...
824 * @param [type] $suffix: ...
825 * @return [type] ...
826 */
827 function cleanInputVal($conf,$suffix='') {
828 if(($conf['comparison'] >> 5==0) || ($conf['comparison']==32 || $conf['comparison']==33)) {
829 $inputVal = $conf['inputValue'.$suffix];
830 } else {
831 if ($conf['comparison']==39 || $conf['comparison']==38) { // in list:
832 $inputVal = implode(',',t3lib_div::intExplode(',',$conf['inputValue'.$suffix]));
833 } else {
834 $inputVal = doubleval($conf['inputValue'.$suffix]);
835 }
836 }
837 return $inputVal;
838 }
839
840 /**
841 * [Describe function...]
842 *
843 * @param [type] $qcArr: ...
844 * @return [type] ...
845 */
846 function getUserDefQuery ($qcArr) {
847 }
848
849 /**
850 * [Describe function...]
851 *
852 * @return [type] ...
853 */
854 function updateIcon() {
855 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">';
856 }
857
858 /**
859 * [Describe function...]
860 *
861 * @return [type] ...
862 */
863 function getLabelCol() {
864 global $TCA;
865 return $TCA[$this->table]['ctrl']['label'];
866 }
867
868 /**
869 * [Describe function...]
870 *
871 * @param [type] $modSettings: ...
872 * @param [type] $enableList: ...
873 * @return [type] ...
874 */
875 function makeSelectorTable($modSettings,$enableList='table,fields,query,group,order,limit') {
876 $enableArr=explode(',',$enableList);
877 // Make output
878 $TDparams = ' class="bgColor5" nowrap';
879
880 if (in_array('table',$enableArr)) {
881 $out='
882 <tr>
883 <td'.$TDparams.'><strong>Select a table:</strong></td>
884 <td'.$TDparams.'>'.$this->mkTableSelect('SET[queryTable]',$this->table).'</td>
885 </tr>';
886 }
887 if ($this->table) {
888
889 // Init fields:
890 $this->setAndCleanUpExternalLists('queryFields',$modSettings['queryFields'],'uid,'.$this->getLabelCol());
891 $this->setAndCleanUpExternalLists('queryGroup',$modSettings['queryGroup']);
892 $this->setAndCleanUpExternalLists('queryOrder',$modSettings['queryOrder'].','.$modSettings['queryOrder2']);
893
894 // Limit:
895 $this->extFieldLists['queryLimit']=$modSettings['queryLimit'];
896 if (!$this->extFieldLists['queryLimit']) $this->extFieldLists['queryLimit']=100;
897 $parts = t3lib_div::intExplode(',',$this->extFieldLists['queryLimit']);
898 $this->extFieldLists['queryLimit'] = implode(',',array_slice($parts,0,2));
899
900 // Insert Descending parts
901 if ($this->extFieldLists['queryOrder']) {
902 $descParts = explode(',',$modSettings['queryOrderDesc'].','.$modSettings['queryOrder2Desc']);
903 $orderParts = explode(',',$this->extFieldLists['queryOrder']);
904 reset($orderParts);
905 $reList=array();
906 while(list($kk,$vv)=each($orderParts)) {
907 $reList[]=$vv.($descParts[$kk]?' DESC':'');
908 }
909 $this->extFieldLists['queryOrder_SQL'] = implode(',',$reList);
910 }
911
912 // Query Generator:
913 $this->procesData($modSettings['queryConfig'] ? unserialize($modSettings['queryConfig']) : '');
914 // debug($this->queryConfig);
915 $this->queryConfig = $this->cleanUpQueryConfig($this->queryConfig);
916 // debug($this->queryConfig);
917 $this->enableQueryParts = $modSettings['search_query_smallparts'];
918
919 $codeArr=$this->getFormElements();
920 $queryCode=$this->printCodeArray($codeArr);
921
922 if (in_array('fields',$enableArr)) {
923 $out.='
924 <tr>
925 <td'.$TDparams.'><strong>Select fields:</strong></td>
926 <td'.$TDparams.'>'.$this->mkFieldToInputSelect('SET[queryFields]',$this->extFieldLists['queryFields']).'</td>
927 </tr>';
928 }
929 if (in_array('query',$enableArr)) {
930 $out.='<tr>
931 <td colspan="2"'.$TDparams.'><strong>Make Query:</strong></td>
932 </tr>
933 <tr>
934 <td colspan="2">'.$queryCode.'</td>
935 </tr>
936 ';
937 }
938 if (in_array('group',$enableArr)) {
939 $out.='<tr>
940 <td'.$TDparams.'><strong>Group By:</strong></td>
941 <td'.$TDparams.'>'.$this->mkTypeSelect('SET[queryGroup]',$this->extFieldLists['queryGroup'],'').'</td>
942 </tr>';
943 }
944 if (in_array('order',$enableArr)) {
945 $orderByArr = explode(',',$this->extFieldLists['queryOrder']);
946 // debug($orderByArr);
947 $orderBy='';
948 $orderBy.=$this->mkTypeSelect('SET[queryOrder]',$orderByArr[0],'').
949 '&nbsp;'.t3lib_BEfunc::getFuncCheck($GLOBALS['SOBE']->id,'SET[queryOrderDesc]',$modSettings['queryOrderDesc']).'&nbsp;Descending';
950 if ($orderByArr[0]) {
951 $orderBy.= '<BR>'.$this->mkTypeSelect('SET[queryOrder2]',$orderByArr[1],'').
952 '&nbsp;'.t3lib_BEfunc::getFuncCheck($GLOBALS['SOBE']->id,'SET[queryOrder2Desc]',$modSettings['queryOrder2Desc']).'&nbsp;Descending';
953 }
954 $out.='<tr>
955 <td'.$TDparams.'><strong>Order By:</strong></td>
956 <td'.$TDparams.'>'.$orderBy.'</td>
957 </tr>';
958 }
959 if (in_array('limit',$enableArr)) {
960 $limit = '<input type="Text" value="'.htmlspecialchars($this->extFieldLists['queryLimit']).'" name="SET[queryLimit]"'.$GLOBALS['TBE_TEMPLATE']->formWidth(10).'>'.$this->updateIcon();
961 $out.='<tr>
962 <td'.$TDparams.'><strong>Limit:</strong></td>
963 <td'.$TDparams.'>'.$limit.'</td>
964 </tr>
965 ';
966 }
967 }
968 $out='<table border="0" cellpadding="3" cellspacing="1">'.$out.'</table>';
969 $out.=$this->JSbottom();
970 return $out;
971 }
972
973 /**
974 * [Describe function...]
975 *
976 * @param [type] $qString: ...
977 * @return [type] ...
978 */
979 function getSelectQuery($qString='') {
980 if (!$qString) $qString=$this->getQuery($this->queryConfig);
981
982 $query = $GLOBALS['TYPO3_DB']->SELECTquery(
983 $this->extFieldLists['queryFields'],
984 $this->table,
985 $qString.t3lib_BEfunc::deleteClause($this->table),
986 trim($this->extFieldLists['queryGroup']),
987 $this->extFieldLists['queryOrder'] ? trim($this->extFieldLists['queryOrder_SQL']) : '',
988 $this->extFieldLists['queryLimit']
989 );
990 return $query;
991 }
992
993 /**
994 * [Describe function...]
995 *
996 * @param [type] $formname: ...
997 * @return [type] ...
998 */
999 function JSbottom($formname='forms[0]') {
1000 if ($this->extJSCODE) {
1001 $out.='
1002 <script language="javascript" type="text/javascript" src="'.$GLOBALS['BACK_PATH'].'t3lib/jsfunc.evalfield.js"></script>
1003 <script language="javascript" type="text/javascript">
1004 var evalFunc = new evalFunc;
1005 function typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue) {
1006 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
1007 var theValue = document.'.$formname.'[theField].value;
1008 if (checkbox && theValue==checkboxValue) {
1009 document.'.$formname.'[theField+"_hr"].value="";
1010 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "";
1011 } else {
1012 document.'.$formname.'[theField+"_hr"].value = evalFunc.outputObjValue(theFObj, theValue);
1013 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "on";
1014 }
1015 }
1016
1017 /**
1018 * [Describe function...]
1019 *
1020 * @param [type] $theField, evallist, is_in, checkbox, checkboxValue, checkbox_off: ...
1021 * @return [type] ...
1022 */
1023 function typo3FormFieldGet(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off) {
1024 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
1025 if (checkbox_off) {
1026 document.'.$formname.'[theField].value=checkboxValue;
1027 }else{
1028 document.'.$formname.'[theField].value = evalFunc.evalObjValue(theFObj, document.'.$formname.'[theField+"_hr"].value);
1029 }
1030 typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue);
1031 }
1032 </script>
1033 <script language="javascript" type="text/javascript">'.$this->extJSCODE.'</script>';
1034 return $out;
1035 }
1036 }
1037 }
1038
1039
1040 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_querygenerator.php']) {
1041 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_querygenerator.php']);
1042 }
1043 ?>