Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.DetailSearch.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Detailled search
8  */
9 namespace Dcp\Core;
11 {
12  /**
13  * Last suggestion for constraints
14  * @var string
15  */
16  private $last_sug;
17 
18  var $defaultedit = "FREEDOM:EDITDSEARCH"; #N_("include") N_("equal") N_("equal") _("not equal") N_("is empty") N_("is not empty") N_("one value equal")
19  var $defaultview = "FREEDOM:VIEWDSEARCH"; #N_("not include") N_("begin by") N_("not equal") N_("&gt; or equal") N_("&lt; or equal") N_("content file word") N_("content file expression")
20 
21  /**
22  * @var \DocFam|null
23  */
24  protected $searchfam = null;
25  /**
26  * return sql query to search wanted document
27  */
28  function ComputeQuery($keyword = "", $famid = - 1, $latest = "yes", $sensitive = false, $dirid = - 1, $subfolder = true, $full = false)
29  {
30 
31  if ($dirid > 0) {
32 
33  if ($subfolder) $cdirid = getRChildDirId($this->dbaccess, $dirid);
34  else $cdirid = $dirid;
35  } else $cdirid = 0;;
36 
37  $filters = $this->getSqlGeneralFilters($keyword, $latest, $sensitive);
38  $cond = $this->getSqlDetailFilter();
39  if ($cond === false) return array(
40  false
41  );
42  $distinct = false;
43  $only = '';
44  if ($latest == "lastfixed") $distinct = true;
45  if ($cond != "") $filters[] = $cond;
46  if ($this->getRawValue("se_famonly") == "yes") {
47  if (!is_numeric($famid)) $famid = getFamIdFromName($this->dbaccess, $famid);
48  $only = "only";
49  }
50  $query = getSqlSearchDoc($this->dbaccess, $cdirid, $famid, $filters, $distinct, $latest == "yes", $this->getRawValue("se_trash") , false, $level = 2, $join = '', $only);
51 
52  return $query;
53  }
54  /**
55  * Change queries when use filters objects instead of declarative criteria
56  * @see DocSearch#getQuery()
57  */
58  function getQuery()
59  {
60  $filtersType = $this->getMultipleRawValues("se_typefilter");
61  if ((count($this->getMultipleRawValues("se_filter")) > 0) && (empty($filtersType[0]) || $filtersType[0] != "generated")) {
62  $queries = array();
63  $filters = $this->getMultipleRawValues("se_filter");
64  foreach ($filters as $filter) {
65  $q = $this->getSqlXmlFilter($filter);
66  if ($q) $queries[] = $q;
67  }
68  return $queries;
69  } else {
70  return parent::getQuery();
71  }
72  }
73 
74  function postStore()
75  {
76  $err = parent::postStore();
77  try {
78  $this->getSqlDetailFilter(true);
79  }
80  catch(\Exception $e) {
81  $err.= $e->getMessage();
82  }
83  $err.= $this->updateFromXmlFilter();
84  $err.= $this->updateXmlFilter();
85  if ((!$err) && ($this->isChanged())) $err = $this->modify();
86  return $err;
87  }
88  /**
89  * @deprecated use postStore() instead
90  * @return string
91  */
92  public function postModify()
93  {
95  return self::postStore();
96  }
97  /**
98  * update somes attributes from Xml filter
99  * @return string error message
100  */
101  public function updateFromXmlFilter()
102  {
103  // update only if one filter
104  $err = '';
105  if (count($this->getMultipleRawValues("se_filter")) == 1) {
106  // try to update se_famid
107  $filters = $this->getMultipleRawValues("se_filter");
108  $filtersType = $this->getMultipleRawValues("se_typefilter");
109  $filter = $filters[0];
110  $filterType = $filtersType[0];
111  if ($filterType != "generated") {
112  $famid = '';
113  $root = simplexml_load_string($filter);
114  $std = $this->simpleXml2StdClass($root);
115  if ($std->family) {
116  if (!is_numeric($std->family)) {
117  if (preg_match("/([\w:]*)\s?(strict)?/", trim($std->family) , $reg)) {
118  if (!is_numeric($reg[1])) $reg[1] = getFamIdFromName($this->dbaccess, $reg[1]);
119  if ($reg[2] == "strict") $famid = '-' . $reg[1];
120  else $famid = $reg[1];
121  }
122  } else {
123  $famid = ($std->family);
124  }
125  if ($famid) {
126  $err = $this->setValue("se_famid", abs($famid));
127  $err.= $this->setValue("se_famonly", ($famid > 0) ? "no" : "yes");
128  }
129  }
130  }
131  }
132  return $err;
133  }
134  /**
135  * update somes attributes from Xml filter
136  * @return string error message
137  */
138  public function updateXmlFilter()
139  {
140  // update only if one filter
141  $err = '';
142  if (count($this->getMultipleRawValues("se_filter")) < 2) {
143  // try to update se_famid
144  $filters = $this->getMultipleRawValues("se_filter");
145  $typeFilters = $this->getMultipleRawValues("se_typefilter");
146  if (count($this->getMultipleRawValues("se_filter")) == 1) {
147  if ($typeFilters[0] != "generated") return ''; // don't update specified filter created by data API
148 
149  }
150  if ($this->getRawValue("se_famid")) {
151  $filterXml = sprintf("<filter><family>%s%s</family>", $this->getRawValue("se_famid") , ($this->getRawValue("se_famonly") == "yes" ? " strict" : ""));
152 
153  $filterXml.= "</filter>";
154  $this->setValue("se_typefilter", "generated"); // only one
155  $this->setValue("se_filter", $filterXml);
156  }
157  }
158  return $err;
159  }
160  /**
161  * return a query from on filter object
162  * @param string $xml xml filter object
163  * @return string the query
164  */
165  function getSqlXmlFilter($xml)
166  {
167  $root = simplexml_load_string($xml);
168  // trasnform XmlObject to StdClass object
169  $std = $this->simpleXml2StdClass($root);
170  $famid = $sql = "";
171  $this->object2SqlFilter($std, $famid, $sql);
172 
173  $filters[] = $sql;
174  $cdirid = 0;
175  $q = getSqlSearchDoc($this->dbaccess, $cdirid, $famid, $filters);
176  if (count($q) == 1) {
177  $q0 = $q[0]; // need a tempo variable : don't know why
178  return ($q0);
179  }
180 
181  return false;
182  }
183  /**
184  * cast SimpleXMLElment to stdClass
185  * @param \SimpleXMLElement $xml
186  * @return \stdClass return object or value if it is a leaf
187  */
188  public function simpleXml2StdClass(\SimpleXMLElement $xml)
189  {
190  $std = null;
191  if ($xml->count() == 0) {
192  return current($xml);
193  } else {
194  foreach ($xml as $k => $se) {
195  if (isset($std->$k)) {
196  if (!is_array($std->$k)) $std->$k = array(
197  $std->$k
198  );
199  array_push($std->$k, $this->simpleXml2StdClass($se));
200  } else {
201  if ($std === null) $std = new \stdClass();
202  $std->$k = $this->simpleXml2StdClass($se);
203  }
204  }
205  }
206  return $std;
207  }
208 
209  function preConsultation()
210  {
211  $err = parent::preConsultation();
212  if ($err !== '') {
213  return $err;
214  }
215  if (count($this->getMultipleRawValues("se_filter")) > 0) {
216  if ($this->defaultview == "FREEDOM:VIEWDSEARCH") {
217  $type = $this->getMultipleRawValues("se_typefilter");
218  if ($type[0] != "generated") {
219  $this->defaultview = "FDL:VIEWBODYCARD";
220  }
221  }
222  }
223  return '';
224  }
225 
226  function preEdition()
227  {
228  if (count($this->getMultipleRawValues("se_filter")) > 0) {
229  $type = $this->getMultipleRawValues("se_typefilter");
230  if ($type[0] != "generated") {
231  $this->defaultedit = "FDL:EDITBODYCARD";
232  /**
233  * @var \NormalAttribute $oa
234  */
235  $this->getAttribute('se_t_detail', $oa);
236  $oa->setVisibility('R');
237  $this->getAttribute('se_t_filters', $oa);
238  $oa->setVisibility('W');
239 
240  $this->getAttribute('se_filter', $oa);
241  $oa->setVisibility('W');
242  }
243  }
244  }
245  /**
246  * return error if query filters are not compatibles
247  * verify parenthesis
248  * @return string error message , empty if no errors
249  */
250  function getSqlParseError()
251  {
252  $err = "";
253  $tlp = $this->getMultipleRawValues("SE_LEFTP");
254  $tlr = $this->getMultipleRawValues("SE_RIGHTP");
255  $clp = 0;
256  $clr = 0;
257  //if (count($tlp) > count($tlr)) $err=sprintf(_("left parenthesis is not closed"));
258  if ($err == "") {
259  foreach ($tlp as $lp) if ($lp == "yes") $clp++;
260  foreach ($tlr as $lr) if ($lr == "yes") $clr++;
261  if ($clp != $clr) $err = sprintf(_("parenthesis number mismatch : %d left, %d right") , $clp, $clr);
262  }
263  return $err;
264  }
265  /**
266  * Check the given string is a valid timestamp (or date)
267  *
268  * @param $str
269  * @return string empty string if valid or error message
270  */
271  private function isValidTimestamp($str)
272  {
273  $this->last_sug = '';
274  /* Check french format */
275  if (preg_match('|^\d\d/\d\d/\d\d\d\d(\s+\d\d:\d\d(:\d\d)?)?$|', $str)) {
276  return '';
277  }
278  /* Check ISO format */
279  if (preg_match('@^\d\d\d\d-\d\d-\d\d([\s+|T]\d\d:\d\d(:\d\d)?)?$@', $str)) {
280  return '';
281  }
282  $this->last_sug = $this->getDate(0, '', '', true);
283  return _("DetailSearch:malformed timestamp").": $str";
284  }
285  /**
286  * Check the given string is a valid Postgresql's RE
287  *
288  * @param string $str
289  * @return string empty string if valid or error message
290  */
291  private function isValidPgRegex($str)
292  {
293  $err = '';
294  $this->last_sug = '';
295  $point = "dcp:isValidPgRegex";
296  $this->savePoint($point);
297  $q = sprintf("SELECT regexp_matches('', E'%s')", pg_escape_string($str));
298  try {
299  simpleQuery($this->dbaccess, $q, $res);
300  }
301  catch(\Exception $e) {
302  $err = $e->getMessage();
303  }
304  $this->rollbackPoint($point);
305  if ($err != '') {
306  $err = _("invalid regular expression");
307  $this->last_sug = preg_quote($str, '');
308  }
309  return $err;
310  }
311  /**
312  * Check validity of a condition tuple (attr, op, value)
313  *
314  * @param string $attr The attribute for the condition
315  * @param string $op The operator for the condition
316  * @param string $value The value for the condition
317  * @return string empty string if valid or error message
318  */
319  public function isValidCondition($attr, $op, $value)
320  {
321  /* Accept method name */
322  if ($value !== '' && $this->getMethodName($value) !== '') {
323  return array(
324  'err' => '',
325  'sug' => ''
326  );
327  }
328  /* Accept parameter */
329  if (substr($value, 0, 1) == '?') {
330  return array(
331  'err' => '',
332  'sug' => ''
333  );
334  }
335  /* Call getSqlCond() in validation mode (validateCond = true) */
336  $err = '';
337  $this->getSqlCond($attr, $op, $value, '', $err, true);
338  if ($err != '') {
339  $err = sprintf(_("Invalid condition for attribute '%s' with value '%s': %s") , $attr, $value, $err);
340  }
341  return array(
342  'err' => $err,
343  'sug' => isset($this->last_sug) ? $this->last_sug : ''
344  );
345  }
346  /**
347  * Check for properly balanced conditions' parenthesis
348  */
349  private function checkConditionsParens()
350  {
351  $err = '';
352  $lp = $this->getMultipleRawValues('se_leftp');
353  $rp = $this->getMultipleRawValues('se_rightp');
354  $pc = 0;
355  foreach ($lp as $p) {
356  if ($p == 'yes') {
357  $pc++;
358  }
359  }
360  foreach ($rp as $p) {
361  if ($p == 'yes') {
362  $pc--;
363  }
364  }
365  if ($pc != 0) {
366  $err = _("DetailSearch:unbalanced parenthesis");
367  }
368  return $err;
369  }
370  /**
371  * Check global coherence of conditions
372  */
373  public function checkConditions()
374  {
375  $err = '';
376  $err.= $this->checkConditionsParens();
377  return array(
378  'err' => $err,
379  'sug' => ''
380  );
381  }
382  /**
383  * return sql part from operator
384  * @param string $col a column : property or attribute name
385  * @param string $op one of this ::top keys : =, !=, >, ....
386  * @param string $val value use for test
387  * @param string $val2 second value use for test with >< operator
388  * @return string the sql query part
389  */
390  function getSqlCond($col, $op, $val = "", $val2 = "", &$err = "", $validateCond = false)
391  {
392 
393  if ((!$this->searchfam) || ($this->searchfam->id != $this->getRawValue("se_famid"))) {
394  $this->searchfam = \new_Doc($this->dbaccess, $this->getRawValue("se_famid"));
395  }
396  $col = trim(strtok($col, ' ')); // a col is one word only (prevent injection)
397  // because for historic reason revdate is not a date type
398  if (($col == "revdate") && ($val != '') && (!is_numeric($val))) {
399  $val = stringdatetounixts($val);
400  }
401  $stateCol = '';
402  if ($col == "activity" || $col == "fixstate") {
403  $stateCol = $col;
404  $col = "state";
405  }
406  $atype = '';
407  $oa = $this->searchfam->getAttribute($col);
408  /**
409  * @var \NormalAttribute $oa
410  */
411  if ($oa) {
412  $atype = $oa->type;
413  } elseif (!empty(\Doc::$infofields[$col])) {
414  $atype = \Doc::$infofields[$col]["type"];
415  }
416  if (($atype == "date" || $atype == "timestamp")) {
417  if ($col == 'revdate') {
418  if ($op == "=") {
419  $val2 = $val + 85399; // tonight
420  $op = "><";
421  }
422  } else {
423  $hms = '';
424  if (($atype == "timestamp")) {
425  $pos = strpos($val, ' ');
426  if ($pos != false) {
427  $hms = substr($val, $pos + 1);
428  }
429  }
430 
431  $cfgdate = getLocaleConfig();
432  if ($val) {
433  $val = stringDateToIso($val, $cfgdate['dateFormat']);
434  }
435  if ($val2) {
436  $val2 = stringDateToIso($val2, $cfgdate['dateFormat']);
437  }
438 
439  if (($atype == "timestamp") && ($op == "=")) {
440 
441  $val = trim($val);
442  if (strlen($val) == 10) {
443  if ($hms == '') {
444  $val2 = $val . " 23:59:59";
445  $val.= " 00:00:00";
446  $op = "><";
447  } elseif (strlen($hms) == 2) {
448  $val2 = $val . ' ' . $hms . ":59:59";
449  $val.= ' ' . $hms . ":00:00";
450  $op = "><";
451  } elseif (strlen($hms) == 5) {
452  $val2 = $val . ' ' . $hms . ":59";
453  $val.= ' ' . $hms . ":00";
454  $op = "><";
455  } else {
456  $val.= ' ' . $hms;
457  }
458  }
459  }
460 
461  if ($validateCond && in_array($op, array(
462  "=",
463  "!=",
464  ">",
465  "<",
466  ">=",
467  "<=",
468  "~y"
469  ))) {
470  if (($err = $this->isValidTimestamp($val)) != '') {
471  return '';
472  }
473  }
474  }
475  }
476  $cond = '';
477  switch ($op) {
478  case "is null":
479 
480  switch ($atype) {
481  case "int":
482  case "uid":
483  case "double":
484  case "money":
485  $cond = sprintf(" (%s is null or %s = 0) ", $col, $col);
486  break;
487 
488  case "date":
489  case "time":
490  $cond = sprintf(" (%s is null) ", $col);
491  break;
492 
493  default:
494  $cond = sprintf(" (%s is null or %s = '') ", $col, $col);
495  }
496 
497  break;
498 
499  case "is not null":
500  $cond = " " . $col . " " . trim($op) . " ";
501  break;
502 
503  case "~*":
504  if ($validateCond) {
505  if (($err = $this->isValidPgRegex($val)) != '') {
506  return '';
507  }
508  }
509  if (trim($val) != "") {
510  $cond = " " . $col . " " . trim($op) . " " . $this->_pg_val($val) . " ";
511  }
512  break;
513 
514  case "~^":
515  if ($validateCond) {
516  if (($err = $this->isValidPgRegex($val)) != '') {
517  return '';
518  }
519  }
520  if (trim($val) != "") {
521  $cond = " " . $col . "~* '^" . pg_escape_string(trim($val)) . "' ";
522  }
523  break;
524 
525  case "~y":
526  if (!is_array($val)) {
527  $val = $this->rawValueToArray($val);
528  }
529  foreach ($val as & $v) {
530  $v = self::pgRegexpQuote($v);
531  }
532  unset($v);
533  if (count($val) > 0) {
534  $cond = " " . $col . " ~ E'\\\\y(" . pg_escape_string(implode('|', $val)) . ")\\\\y' ";
535  }
536  break;
537 
538  case "><":
539  if ((trim($val) != "") && (trim($val2) != "")) {
540  $cond = sprintf("%s >= %s and %s <= %s", $col, $this->_pg_val($val) , $col, $this->_pg_val($val2));
541  }
542  break;
543 
544  case "=~*":
545  switch ($atype) {
546  case "uid":
547  if ($validateCond) {
548  if (($err = $this->isValidPgRegex($val)) != '') {
549  return '';
550  }
551  }
552  $err = simpleQuery(getDbAccessCore() , sprintf("select id from users where firstname ~* '%s' or lastname ~* '%s'", pg_escape_string($val) , pg_escape_string($val)) , $ids, true);
553  if ($err == "") {
554  if (count($ids) == 0) {
555  $cond = "false";
556  } elseif (count($ids) == 1) {
557  $cond = " " . $col . " = " . intval($ids[0]) . " ";
558  } else {
559  $cond = " " . $col . " in (" . implode(',', $ids) . ") ";
560  }
561  }
562  break;
563 
564  case "account":
565  case "docid":
566  if ($validateCond) {
567  if (($err = $this->isValidPgRegex($val)) != '') {
568  return '';
569  }
570  }
571  if ($oa) {
572  $otitle = $oa->getOption("doctitle");
573  if (!$otitle) {
574  $fid = $oa->format;
575  if (!$fid && $oa->type == "account") {
576  $fid = "IUSER";
577  }
578  if (!$fid) {
579  $err = sprintf(_("no compatible type with operator %s") , $op);
580  } else {
581  if (!is_numeric($fid)) {
582  $fid = getFamidFromName($this->dbaccess, $fid);
583  }
584  $err = simpleQuery($this->dbaccess, sprintf("select id from doc%d where title ~* '%s'", $fid, pg_escape_string($val)) , $ids, true);
585  if ($err == "") {
586  if (count($ids) == 0) {
587  $cond = "false";
588  } elseif (count($ids) == 1) {
589  $cond = " " . $col . " = '" . intval($ids[0]) . "' ";
590  } else {
591  $cond = " " . $col . " in ('" . implode("','", $ids) . "') ";
592  }
593  }
594  }
595  } else {
596  if ($otitle == "auto") {
597  $otitle = $oa->id . "_title";
598  }
599  $oat = $this->searchfam->getAttribute($otitle);
600  if ($oat) {
601  $cond = " " . $oat->id . " ~* '" . pg_escape_string(trim($val)) . "' ";
602  } else {
603  $err = sprintf(_("attribute %s : cannot detect title attribute") , $col);
604  }
605  }
606  } elseif ($col == "fromid") {
607  $err = simpleQuery($this->dbaccess, sprintf("select id from docfam where title ~* '%s'", pg_escape_string($val)) , $ids, true);
608  if ($err == "") {
609  if (count($ids) == 0) {
610  $cond = "false";
611  } elseif (count($ids) == 1) {
612  $cond = " " . $col . " = " . intval($ids[0]) . " ";
613  } else {
614  $cond = " " . $col . " in (" . implode(",", $ids) . ") ";
615  }
616  }
617  }
618  break;
619 
620  default:
621  if ($atype) {
622  $err = sprintf(_("attribute %s : %s type is not allowed with %s operator") , $col, $atype, $op);
623  } else {
624  $err = sprintf(_("attribute %s not found [%s]") , $col, $atype);
625  }
626  }
627  break;
628 
629  case "~@":
630  if ($validateCond) {
631  if (($err = $this->isValidPgRegex($val)) != '') {
632  return '';
633  }
634  }
635  if (trim($val) != "") {
636  $cond = " " . $col . '_txt' . " ~ '" . strtolower($val) . "' ";
637  }
638  break;
639 
640  case "=@":
641  case "@@":
642  if (trim($val) != "") {
643  $tstatickeys = explode(' ', $val);
644  if (count($tstatickeys) > 1) {
645  $keyword = str_replace(" ", "&", trim($val));
646  } else {
647  $keyword = trim($val);
648  }
649  if ($op == "@@") {
650  $cond = " " . $col . '_vec' . " @@ to_tsquery('french','." . pg_escape_string(unaccent(strtolower($keyword))) . "') ";
651  } elseif ($op == "=@") {
652  $cond = sprintf("fulltext @@ to_tsquery('french','%s') ", pg_escape_string(unaccent(strtolower($keyword))));
653  }
654  }
655  break;
656 
657  default:
658 
659  switch ($atype) {
660  case "enum":
661  $enum = $oa->getEnum();
662  if (strrpos($val, '.') !== false) {
663  $val = substr($val, strrpos($val, '.') + 1);
664  }
665  $tkids = array();;
666  foreach ($enum as $k => $v) {
667  if (in_array($val, explode(".", $k))) {
668  $tkids[] = substr($k, strrpos("." . $k, '.'));
669  }
670  }
671 
672  if ($op == '=') {
673  if ($oa->repeat) {
674  $cond = " " . $col . " ~ E'\\\\y(" . pg_escape_string(implode('|', $tkids)) . ")\\\\y' ";
675  } else {
676  $cond = " $col='" . implode("' or $col='", $tkids) . "'";
677  }
678  } elseif ($op == '!=') {
679  if ($oa->repeat) {
680  $cond1 = " " . $col . " !~ E'\\\\y(" . pg_escape_string(implode('|', $tkids)) . ")\\\\y' ";
681  } else {
682  $cond1 = " $col !='" . implode("' and $col != '", $tkids) . "'";
683  }
684  $cond = " (($cond1) or ($col is null))";
685  } elseif ($op == '!~*') {
686  if ($validateCond) {
687  if (($err = $this->isValidPgRegex($val)) != '') {
688  return '';
689  }
690  }
691  $cond = sprintf("( (%s is null) or (%s %s %s) )", $col, $col, trim($op) , $this->_pg_val($val));
692  }
693 
694  break;
695 
696  default:
697  if ($atype == "docid") {
698  if (!is_numeric($val)) $val = getIdFromName($this->dbaccess, $val);
699  }
700  $cond1 = " " . $col . " " . trim($op) . $this->_pg_val($val) . " ";
701  if (($op == '!=') || ($op == '!~*')) {
702  if ($validateCond && $op == '!~*') {
703  if (($err = $this->isValidPgRegex($val)) != '') {
704  return '';
705  }
706  }
707  $cond = "(($cond1) or ($col is null))";
708  } else {
709  $cond = $cond1;
710  }
711  }
712  }
713  if (!$cond) {
714  $cond = "true";
715  } elseif ($stateCol == "activity") {
716  $cond = sprintf("(%s and locked != -1)", $cond);
717  } elseif ($stateCol == "fixstate") {
718  $cond = sprintf("(%s and locked = -1)", $cond);
719  }
720  return $cond;
721  }
722 
723  private static function _pg_val($s)
724  {
725  if (substr($s, 0, 2) == ':@') {
726  return " " . trim(strtok(substr($s, 2) , " \t")) . " ";
727  } else return " '" . pg_escape_string(trim($s)) . "' ";
728  }
729  /**
730  * return array of sql filter needed to search wanted document
731  */
732  function getSqlDetailFilter($validateCond = false)
733  {
734  $ol = $this->getRawValue("SE_OL");
735  $tkey = $this->getMultipleRawValues("SE_KEYS");
736  $taid = $this->getMultipleRawValues("SE_ATTRIDS");
737  $tf = $this->getMultipleRawValues("SE_FUNCS");
738  $tlp = $this->getMultipleRawValues("SE_LEFTP");
739  $tlr = $this->getMultipleRawValues("SE_RIGHTP");
740  $tols = $this->getMultipleRawValues("SE_OLS");
741 
742  if ($ol == "") {
743  // try in old version
744  $ols = $this->getMultipleRawValues("SE_OLS");
745  $ol = isset($ols[1]) ? $ols[1] : '';
746  if ($ol) {
747  $this->setValue("SE_OL", $ol);
748  $this->modify();
749  }
750  }
751  if ($ol == "") $ol = "and";
752  $cond = "";
753  if (!$this->searchfam) {
754  $this->searchfam = \new_Doc($this->dbaccess, $this->getRawValue("se_famid"));
755  }
756  if ((count($taid) > 1) || (count($taid) > 0 && $taid[0] != "")) {
757  // special loop for revdate
758  foreach ($tkey as $k => $v) {
759  // Does it looks like a method name?
760  $methodName = $this->getMethodName($v);
761  if ($methodName != '') {
762  // it's method call
763  $workdoc = $this->getSearchFamilyDocument();
764  if (!$workdoc) {
765  $workdoc = $this;
766  }
767  if (!$workdoc->isValidSearchMethod($workdoc, $methodName)) {
768  return 'false';
769  }
770  $rv = $workdoc->ApplyMethod($v);
771  $tkey[$k] = $rv;
772  }
773  if (substr($v, 0, 1) == "?") {
774  // it's a parameter
775  $rv = getHttpVars(substr($v, 1) , "-");
776  if ($rv == "-") return (false);
777  if ($rv === "" || $rv === " ") unset($taid[$k]);
778  else $tkey[$k] = $rv;
779  }
780  if ($taid[$k] == "revdate") {
781  if (substr_count($tkey[$k], '/') === 2) {
782  list($dd, $mm, $yyyy) = explode("/", $tkey[$k]);
783  if ($yyyy > 0) $tkey[$k] = mktime(0, 0, 0, $mm, $dd, $yyyy);
784  }
785  }
786  }
787  foreach ($taid as $k => $v) {
788  $cond1 = $this->getSqlCond($taid[$k], trim($tf[$k]) , $tkey[$k], "", $err, $validateCond);
789  if ($validateCond && $err != '') {
790  throw new \Exception($err);
791  }
792  if ($cond == "") {
793  if (isset($tlp[$k]) && $tlp[$k] == "yes") $cond = '(' . $cond1 . " ";
794  else $cond = $cond1 . " ";
795  if (isset($tlr[$k]) && $tlr[$k] == "yes") $cond.= ')';
796  } elseif ($cond1 != "") {
797  if (isset($tols[$k]) && $tols[$k] != "" && $ol === "perso") $ol1 = $tols[$k];
798  else $ol1 = $ol;
799 
800  if ($ol1 === "perso") {
801  // workaround if user set global as condition
802  $ol1 = "and";
803  }
804  if (isset($tlp[$k]) && $tlp[$k] == "yes") $cond.= $ol1 . ' (' . $cond1 . " ";
805  else $cond.= $ol1 . " " . $cond1 . " ";
806  if (isset($tlr[$k]) && $tlr[$k] == "yes") $cond.= ') ';
807  }
808  }
809  }
810  if (trim($cond) == "") $cond = "true";
811  return $cond;
812  }
813  /**
814  * return true if the search has parameters
815  */
816  function isParameterizable()
817  {
818  $tkey = $this->getMultipleRawValues("SE_KEYS");
819  if (empty($tkey)) return false;
820  if ((count($tkey) > 1) || ($tkey[0] != "")) {
821  foreach ($tkey as $k => $v) {
822 
823  if ($v && $v[0] == '?') {
824  return true;
825  //if (getHttpVars(substr($v,1),"-") == "-") return true;
826 
827  }
828  }
829  }
830  return false;
831  }
832  /**
833  * return true if the search need parameters
834  */
835  function needParameters()
836  {
837  $tkey = $this->getMultipleRawValues("SE_KEYS");
838  if ((count($tkey) > 1) || (!empty($tkey[0]))) {
839 
840  foreach ($tkey as $k => $v) {
841 
842  if ($v && $v[0] == '?') {
843  if (getHttpVars(substr($v, 1) , "-") == "-") return true;
844  }
845  }
846  }
847  return false;
848  }
849  /**
850  * Add parameters
851  */
852  function urlWhatEncodeSpec($l)
853  {
854  $tkey = $this->getMultipleRawValues("SE_KEYS");
855 
856  if ((count($tkey) > 1) || (isset($tkey[0]) && $tkey[0] != "")) {
857 
858  foreach ($tkey as $k => $v) {
859 
860  if ($v && $v[0] == '?') {
861  if (getHttpVars(substr($v, 1) , "-") != "-") {
862  $l.= '&' . substr($v, 1) . "=" . getHttpVars(substr($v, 1));
863  }
864  }
865  }
866  }
867 
868  return $l;
869  }
870  /**
871  * add parameters in title
872  */
873  function getCustomTitle()
874  {
875  $tkey = $this->getMultipleRawValues("SE_KEYS");
876  $taid = $this->getMultipleRawValues("SE_ATTRIDS");
877  $l = "";
878  if ((count($tkey) > 1) || (isset($tkey[0]) && $tkey[0] != "")) {
879  $tl = array();
880  foreach ($tkey as $k => $v) {
881 
882  if ($v && $v[0] == '?') {
883  $vh = getHttpVars(substr($v, 1) , "-");
884  if (($vh != "-") && ($vh != "")) {
885 
886  if (is_numeric($vh)) {
887  $fam = $this->getSearchFamilyDocument();
888  if ($fam) {
889  $oa = $fam->getAttribute($taid[$k]);
890  if ($oa && $oa->type == "docid") {
891  $vh = $this->getTitle($vh);
892  }
893  }
894  }
895  $tl[] = $vh;
896  }
897  }
898  }
899  if (count($tl) > 0) {
900  $l = " (" . implode(", ", $tl) . ")";
901  }
902  }
903  return $this->getRawValue("ba_title") . $l;
904  }
905  /**
906  * @templateController default detailed search view
907  * @param string $target
908  * @param bool $ulink
909  * @param bool $abstract
910  */
911  function viewdsearch($target = "_self", $ulink = true, $abstract = false)
912  {
913  // Compute value to be inserted in a layout
914  $this->viewattr();
915  //-----------------------------------------------
916  // display already condition written
917  $tkey = $this->getMultipleRawValues("SE_KEYS");
918  $taid = $this->getMultipleRawValues("SE_ATTRIDS");
919  $tf = $this->getMultipleRawValues("SE_FUNCS");
920  $se_ol = $this->getRawValue(\Dcp\AttributeIdentifiers\Dsearch::se_ol);
921  $se_ols = $this->getMultipleRawValues(\Dcp\AttributeIdentifiers\Dsearch::se_ols);
922  $se_leftp = $this->getMultipleRawValues(\Dcp\AttributeIdentifiers\Dsearch::se_leftp);
923  $se_rightp = $this->getMultipleRawValues(\Dcp\AttributeIdentifiers\Dsearch::se_rightp);
924  if ((count($taid) > 1) || (!empty($taid[0]))) {
925 
926  $fdoc = \new_Doc($this->dbaccess, $this->getRawValue("SE_FAMID", 1));
927  $zpi = $fdoc->GetNormalAttributes();
928  $zpi["state"] = new \BasicAttribute("state", $this->fromid, _("step"));
929  $zpi["fixstate"] = new \BasicAttribute("fixstate", $this->fromid, _("state"));
930  $zpi["activity"] = new \BasicAttribute("activity", $this->fromid, _("activity"));
931  $zpi["title"] = new \BasicAttribute("title", $this->fromid, _("doctitle"));
932  $zpi["revdate"] = new \BasicAttribute("revdate", $this->fromid, _("revdate"));
933  $zpi["cdate"] = new \BasicAttribute("cdate", $this->fromid, _("cdate") , 'W', '', '', 'date');
934  $zpi["revision"] = new \BasicAttribute("cdate", $this->fromid, _("revision"));
935  $zpi["owner"] = new \BasicAttribute("owner", $this->fromid, _("owner"));
936  $zpi["locked"] = new \BasicAttribute("owner", $this->fromid, _("locked"));
937  $zpi["allocated"] = new \BasicAttribute("owner", $this->fromid, _("allocated"));
938  $zpi["svalues"] = new \BasicAttribute("svalues", $this->fromid, _("any values"));
939  $tcond = array();
940  foreach ($taid as $k => $v) {
941  if (isset($zpi[$v])) {
942  $label = $zpi[$v]->getLabel();
943  if ($label == "") $label = $v;
944  if ($v == "activity") {
945  $fdoc->state = $tkey[$k];
946  $displayValue = $fdoc->getStatelabel();
947  } else {
948  $displayValue = ($tkey[$k] != "") ? _($tkey[$k]) : $tkey[$k];
949  }
950  $type = $zpi[$taid[$k]]->type;
951  if ($zpi[$taid[$k]]->isMultiple() || $zpi[$taid[$k]]->inArray()) {
952  if ($type === "docid") $type = "docid[]";
953  else if ($type === "account") $type = "account[]";
954  }
955  $elmts = array();
956  if ($se_ol == 'perso') {
957  if (count($tcond) > 0) {
958  /* Do not display operator on first line */
959  if (isset($se_ols[$k]) && $se_ols[$k] != '') {
960  $elmts[] = _($se_ols[$k]);
961  }
962  }
963  if (isset($se_leftp[$k]) && $se_leftp[$k] == 'yes') {
964  $elmts[] = '(';
965  }
966  $elmts[] = sprintf("%s %s %s", mb_ucfirst($label) , $this->getOperatorLabel($tf[$k], $type) , $displayValue);
967  if (isset($se_rightp[$k]) && $se_rightp[$k] == 'yes') {
968  $elmts[] = ')';
969  }
970  } else {
971  if (count($tcond) > 0) {
972  /* Do not display operator on first line */
973  $elmts[] = _($se_ol);
974  }
975  $elmts[] = sprintf("%s %s %s", mb_ucfirst($label) , $this->getOperatorLabel($tf[$k], $type) , $displayValue);
976  }
977  $tcond[]["condition"] = join(' ', $elmts);
978  if (isset($tkey[$k][0]) && $tkey[$k][0] == '?') {
979  $tparm[substr($tkey[$k], 1) ] = $taid[$k];
980  }
981  } else {
982  addWarningMsg(sprintf("property %s not know", $v));
983  }
984  }
985  $this->lay->SetBlockData("COND", $tcond);
986  }
987  $this->lay->Set("ddetail", "");
988  }
989  /**
990  * return true if the sqlselect is writted by hand
991  * @return bool
992  */
993  function isStaticSql()
994  {
995  return ($this->getRawValue("se_static") != "");
996  }
997  /**
998  * return family use for search
999  * @return \Doc
1000  */
1001  private function getSearchFamilyDocument()
1002  {
1003  static $fam = null;
1004  if (!$fam) $fam = createTmpDoc($this->dbaccess, $this->getRawValue("SE_FAMID", 1));
1005  return $fam;
1006  }
1007  /**
1008  * @templateController
1009  * @param string $target
1010  * @param bool $ulink
1011  * @param bool $abstract
1012  */
1013  function paramdsearch($target = "_self", $ulink = true, $abstract = false)
1014  {
1015  // Compute value to be inserted in a layout
1016  $this->viewattr();
1017  $tparm = $tcond = array();
1018  //-----------------------------------------------
1019  // display already condition written
1020  $tkey = $this->getMultipleRawValues("SE_KEYS");
1021  $taid = $this->getMultipleRawValues("SE_ATTRIDS");
1022  $tf = $this->getMultipleRawValues("SE_FUNCS");
1023  $zpi = $toperator = array();
1024  if ((count($taid) > 1) || ($taid[0] != "")) {
1025 
1026  $fdoc = \new_Doc($this->dbaccess, $this->getRawValue("SE_FAMID", 1));
1027  $zpi = $fdoc->GetNormalAttributes();
1028  $zpi["state"] = new \BasicAttribute("state", $this->fromid, _("step"));
1029  $zpi["fixstate"] = new \BasicAttribute("state", $this->fromid, _("fixstate"));
1030  $zpi["activity"] = new \BasicAttribute("state", $this->fromid, _("activity"));
1031  $zpi["title"] = new \BasicAttribute("title", $this->fromid, _("doctitle"));
1032  $zpi["revdate"] = new \BasicAttribute("revdate", $this->fromid, _("revdate"));
1033  $zpi["cdate"] = new \BasicAttribute("cdate", $this->fromid, _("cdate") , 'W', '', '', 'date');
1034  $zpi["revision"] = new \BasicAttribute("cdate", $this->fromid, _("revision"));
1035  $zpi["owner"] = new \BasicAttribute("owner", $this->fromid, _("owner"));
1036  $zpi["locked"] = new \BasicAttribute("owner", $this->fromid, _("locked"));
1037  $zpi["allocated"] = new \BasicAttribute("owner", $this->fromid, _("allocated"));
1038  $zpi["svalues"] = new \BasicAttribute("svalues", $this->fromid, _("any values"));
1039 
1040  foreach ($taid as $k => $v) {
1041  if ($tkey[$k][0] == '?') {
1042  $tparm[substr($tkey[$k], 1) ] = $taid[$k];
1043  $toperator[substr($tkey[$k], 1) ] = $tf[$k];
1044  }
1045  }
1046  $this->lay->SetBlockData("COND", $tcond);
1047  }
1048 
1049  $this->lay->Set("ddetail", "");
1050  if (count($tparm) > 0) {
1051  include_once ("FDL/editutil.php");
1052  global $action;
1053  editmode($action);
1054 
1055  $doc = $this->getSearchFamilyDocument();
1056  $inputset = array();
1057  $ki = 0; // index numeric
1058  $tinputs = $ttransfert = array();
1059  foreach ($tparm as $k => $v) {
1060  if (isset($inputset[$v])) {
1061  // need clone when use several times the same attribute
1062  $vz = $v . "Z" . $ki;
1063  $zpi[$vz] = $zpi[$v];
1064  $zpi[$vz]->id = $vz;
1065  $v = $vz;
1066  }
1067  if ($zpi[$v]->fieldSet->type == 'array') $zpi[$v]->fieldSet->type = 'frame'; // no use array configuration for help input
1068  $ki++;
1069  $inputset[$v] = true;
1070 
1071  $ttransfert[] = array(
1072  "idi" => $v,
1073  "idp" => $k,
1074  "value" => getHttpVars($k)
1075  );
1076  $tinputs[$k]["label"] = $zpi[$v]->getLabel();
1077  $type = $zpi[$v]->type;
1078  if ($zpi[$v]->isMultiple() || $zpi[$v]->inArray()) {
1079  if ($type === "docid") $type = "docid[]";
1080  else if ($type === "account") $type = "account[]";
1081  }
1082  $tinputs[$k]["operator"] = $this->getOperatorLabel($toperator[$k], $type);
1083  if (($toperator[$k] == "=~*" || $toperator[$k] == "~*") && $zpi[$v]->type == "docid") $zpi[$v]->type = "text"; // present like a search when operator is text search
1084  if ($zpi[$v]->visibility == 'R') $zpi[$v]->mvisibility = 'W';
1085  if ($zpi[$v]->visibility == 'S') $zpi[$v]->mvisibility = 'W';
1086  if (isset($zpi[$v]->id)) {
1087  $zpi[$v]->isAlone = true;
1088  $tinputs[$k]["inputs"] = getHtmlInput($doc, $zpi[$v], getHttpVars($k));
1089  } else {
1090  $aotxt = new \BasicAttribute($v, $doc->id, "eou");
1091  if ($v == "revdate") $aotxt->type = "date";
1092  /** @noinspection PhpParamsInspection */
1093  $tinputs[$k]["inputs"] = getHtmlInput($doc, $aotxt, getHttpVars($k));
1094  }
1095  }
1096  $this->lay->setBlockData("PARAM", $tinputs);
1097  $this->lay->setBlockData("TRANSFERT", $ttransfert);
1098  $this->lay->setBlockData("PINPUTS", $ttransfert);
1099  $this->lay->eSet("ddetail", "none");
1100  $this->lay->eset("stext", _("send search"));
1101  $this->lay->eset("saction", getHttpVars("saction", "FREEDOM_VIEW"));
1102  $this->lay->eset("sapp", getHttpVars("sapp", "FREEDOM"));
1103  $this->lay->eset("sid", getHttpVars("sid", "dirid"));
1104  $this->lay->eset("starget", getHttpVars("starget", ""));
1105  $this->lay->set("icon", $this->getIcon());
1106  }
1107  }
1108  // -----------------------------------
1109 
1110  /**
1111  *
1112  * @templateController default detailed search edit view
1113  */
1114  function editdsearch()
1115  {
1116  /**
1117  * @var \Action $action
1118  */
1119  global $action;
1120  $classid = GetHttpVars("sfamid", 0);
1121  $famid = $this->getRawValue("SE_FAMID", 0);
1122  $onlysubfam = GetHttpVars("onlysubfam"); // restricy to sub fam of
1123  $dirid = GetHttpVars("dirid");
1124  $alsosub = getHttpVars("alsosub") == "Y";
1125  $this->lay->set("ACTION", urlencode($action->name));
1126  $tclassdoc = array();
1127  $action->parent->AddJsRef($action->GetParam("CORE_PUBURL") . "/lib/jquery/jquery.js");
1128  $action->parent->AddJsRef($action->GetParam("CORE_PUBURL") . "/FDL/Layout/edittable.js");
1129  $action->parent->AddJsRef($action->GetParam("CORE_PUBURL") . "/FREEDOM/Layout/editdsearch.js");
1130 
1131  if ($dirid > 0) {
1132  /**
1133  * @var \Dir $dir
1134  */
1135  $dir = \new_Doc($this->dbaccess, $dirid);
1136  if (method_exists($dir, "isAuthorized")) {
1137  if ($dir->isAuthorized($classid)) {
1138  // verify if classid is possible
1139  if ($dir->hasNoRestriction()) {
1140  $tclassdoc = GetClassesDoc($this->dbaccess, $action->user->id, $classid, "TABLE");
1141  $tclassdoc[] = array(
1142  "id" => 0,
1143  "title" => _("any families") ,
1144  "usefor" => ''
1145  );
1146  } else {
1147  $tclassdoc = $dir->getAuthorizedFamilies();
1148  $this->lay->set("restrict", true);
1149  }
1150  } else {
1151  $tclassdoc = $dir->getAuthorizedFamilies();
1152  $first = current($tclassdoc);
1153  $famid1 = ($first["id"]);
1154  $this->lay->set("restrict", true);
1155  $tfamids = array_keys($tclassdoc);
1156  if (!in_array($famid, $tfamids)) $famid = $famid1;
1157  }
1158  } else {
1159  $tclassdoc = GetClassesDoc($this->dbaccess, $action->user->id, $classid, "TABLE");
1160  }
1161  } else {
1162  if ($onlysubfam) {
1163  if (!is_numeric($onlysubfam)) $onlysubfam = getFamIdFromName($this->dbaccess, $onlysubfam);
1164  $cdoc = \new_Doc($this->dbaccess, $onlysubfam);
1165  $tsub = $cdoc->GetChildFam($cdoc->id, false);
1166  $tclassdoc[$classid] = array(
1167  "id" => $cdoc->id,
1168  "title" => $cdoc->title,
1169  "usefor" => ''
1170  );
1171  if ($alsosub) {
1172  $tclassdoc = array_merge($tclassdoc, $tsub);
1173  }
1174  if (!$this->id) $this->setValue("se_famonly", $alsosub ? "no" : "yes");
1175  $first = current($tclassdoc);
1176  if ($classid == "") $classid = $first["id"];
1177  } else {
1178  $tclassdoc = GetClassesDoc($this->dbaccess, $action->user->id, $classid, "TABLE");
1179  $tclassdoc[] = array(
1180  "id" => 0,
1181  "title" => _("any families") ,
1182  "usefor" => ''
1183  );
1184  }
1185  }
1186  $sLabelArray = array();
1187  foreach ($this->top as $k => $v) {
1188  $sLabel = array();
1189  if (isset($v["slabel"]) && is_array($v["slabel"])) {
1190  foreach ($v["slabel"] as $key => $value) {
1191  $sLabel[$key] = _($value);
1192  }
1193  }
1194  $sLabelArray[$k] = array(
1195  "label" => _($v["label"]) ,
1196  "slabel" => $sLabel
1197  );
1198  }
1199  $this->lay->set("topInformation", json_encode($sLabelArray));
1200  $this->lay->set("onlysubfam", urlencode($onlysubfam));
1201  $selfam = false;
1202  $selectclass = array();
1203  foreach ($tclassdoc as $k => $tdoc) {
1204  $selectclass[$k]["idcdoc"] = $tdoc["id"];
1205  $selectclass[$k]["classname"] = $tdoc["title"];
1206  $selectclass[$k]["system_fam"] = (substr($tdoc["usefor"], 0, 1) == 'S') ? true : false;
1207  if (abs($tdoc["id"]) == abs($famid)) {
1208  $selfam = true;
1209  $selectclass[$k]["selected"] = 'selected="selected"';
1210  if ($famid < 0) $this->lay->set("selfam", $tdoc["title"] . " " . _("(only)"));
1211  else $this->lay->set("selfam", $tdoc["title"]);
1212  } else $selectclass[$k]["selected"] = "";
1213  }
1214  if (!$selfam) {
1215  $famid = abs($this->getRawValue("se_famid"));
1216  if ($this->id && $famid) {
1217  $selectclass[] = array(
1218  "idcdoc" => $famid,
1219  "classname" => $this->getTitle($famid) ,
1220  "selected" => "selected"
1221  );
1222  } else {
1223  reset($tclassdoc);
1224  $first = current($tclassdoc);
1225  $famid = $first["id"];
1226  }
1227  }
1228  $this->lay->Set("dirid", urlencode($dirid));
1229  $this->lay->Set("classid", $this->fromid);
1230  $this->lay->SetBlockData("SELECTCLASS", $selectclass);
1231  $this->lay->set("has_permission_fdl_system", $action->parent->hasPermission('FDL', 'SYSTEM'));
1232  $this->lay->set("se_sysfam", ($this->getRawValue('se_sysfam') == 'yes') ? true : false);
1233  $this->setFamidInLayout();
1234  // display attributes
1235  $tattr = array();
1236  $internals = array(
1237  "title" => _("doctitle") ,
1238  "revdate" => _("revdate") ,
1239  "cdate" => _("cdate") ,
1240  "revision" => _("revision") ,
1241  "owner" => _("id owner") ,
1242  "locked" => _("id locked") ,
1243  "allocated" => _("id allocated") ,
1244  "svalues" => _("any values")
1245  );
1246 
1247  $tattr["_prop"] = array(
1248  "attrid" => "_prop",
1249  "attrtype" => "set",
1250  "attrdisabled" => "disabled",
1251  "attrname" => _("DocProperties") ,
1252  "ismultiple" => 'no'
1253  );
1254 
1255  foreach ($internals as $k => $v) {
1256  if ($k == "revdate") $type = "date";
1257  else if ($k == "owner") $type = "uid";
1258  else if ($k == "locked") $type = "uid";
1259  else if ($k == "allocated") $type = "uid";
1260  else if ($k == "cdate") $type = "date";
1261  else if ($k == "revision") $type = "int";
1262  else if ($k == "state") $type = "docid";
1263  else $type = "text";
1264 
1265  $tattr[$k] = array(
1266  "attrid" => $k,
1267  "ismultiple" => 'no',
1268  "attrtype" => $type,
1269  "attrdisabled" => "",
1270  "attrname" => $v
1271  );
1272  }
1273 
1274  $fdoc = \new_Doc($this->dbaccess, abs($famid));
1275  $tmpDoc = \createTmpDoc($this->dbaccess, abs($famid));
1276  $zpi = $fdoc->GetNormalAttributes();
1277 
1278  foreach ($zpi as $k => $v) {
1279  if ($v->type == "array" || $v->type == "password") {
1280  continue;
1281  }
1282  $opt_searchcriteria = $v->getOption("searchcriteria", "");
1283  if ($opt_searchcriteria == "hidden" || $opt_searchcriteria == "restricted") {
1284  continue;
1285  }
1286 
1287  $type = $v->type;
1288  if ($v->getOption("doctitle") && $v->isMultiple()) $type = "docidtitle[]";
1289  $tset = $this->editGetSetAttribute($v->fieldSet);
1290  if (count($tset) > 0) $tattr = array_merge($tattr, array_reverse($tset));
1291 
1292  $tattr[$v->id] = array(
1293  "attrid" => $v->id,
1294  "ismultiple" => ($v->isMultiple()) ? 'yes' : 'no',
1295  "attrtype" => $type,
1296  "attrdisabled" => "",
1297  "attrname" => $v->getLabel()
1298  );
1299  }
1300  if ($action->getParam("ISIE6")) {
1301  // cannot disable select option with IE6
1302  foreach ($tattr as $ka => $va) {
1303  if (!empty($va["attrdisabled"])) unset($tattr[$ka]);
1304  }
1305  }
1306  $this->lay->SetBlockData("ATTR", $tattr);
1307  $tfunc = array();
1308  foreach ($this->top as $k => $v) {
1309  $display = '';
1310  if (isset($v["type"])) {
1311  $ctype = implode(",", $v["type"]);
1312  if (!in_array('text', $v["type"])) $display = 'none'; // first is title
1313 
1314  } else $ctype = "";
1315 
1316  $tfunc[] = array(
1317  "funcid" => $k,
1318  "functype" => $ctype,
1319  "funcdisplay" => $display,
1320  "funcname" => _($v["label"])
1321  );
1322  }
1323  $this->lay->SetBlockData("FUNC", $tfunc);
1324  foreach ($tfunc as $k => $v) {
1325  if (($v["functype"] != "") && (strpos($v["functype"], "enum") === false)) unset($tfunc[$k]);
1326  }
1327  $this->lay->SetBlockData("FUNCSTATE", $tfunc);
1328  $this->lay->Set("icon", $fdoc->getIcon());
1329 
1330  if ($this->getRawValue("SE_LATEST") == "no") $this->lay->Set("select_all", "selected");
1331  else $this->lay->Set("select_all", "");
1332  $states = array();
1333  //-----------------------------------------------
1334  // display state
1335  $wdoc = null;
1336  if ($fdoc->wid > 0) {
1337  $wdoc = \new_Doc($this->dbaccess, $fdoc->wid);
1338  /**
1339  * @var \Wdoc $wdoc
1340  */
1341  $states = $wdoc->getStates();
1342 
1343  $tstates = array();
1344  foreach ($states as $k => $v) {
1345  $tstates[] = array(
1346  "step" => "state",
1347  "stateid" => $v,
1348  "statename" => _($v)
1349  );
1350  $activity = $wdoc->getActivity($v);
1351 
1352  $tstates[] = array(
1353  "step" => "activity",
1354  "stateid" => $v,
1355  "statename" => ($activity) ? _($activity) : _($v)
1356  );
1357  }
1358  $this->lay->SetBlockData("STATE", $tstates);
1359  $this->lay->Set("dstate", "inline");
1360  } else {
1361  $this->lay->Set("dstate", "none");
1362  }
1363  //-----------------------------------------------
1364  // display already condition written
1365  $tol = $this->getMultipleRawValues("SE_OLS");
1366  $tkey = $this->getMultipleRawValues("SE_KEYS");
1367  $taid = $this->getMultipleRawValues("SE_ATTRIDS");
1368  $tf = $this->getMultipleRawValues("SE_FUNCS");
1369  $tlp = $this->getMultipleRawValues("SE_LEFTP");
1370  $trp = $this->getMultipleRawValues("SE_RIGHTP");
1371 
1372  $cond = "";
1373  $tcond = array();
1374  if ((count($taid) > 1) || ($taid && $taid[0] != "")) {
1375  foreach ($taid as $k => $keyId) {
1376  $docid_aid = 0;
1377  $v = $tkey[$k];
1378  $oa = $fdoc->getAttribute($keyId);
1379  $tcond[$k] = array(
1380  "OLCOND" => "olcond$k",
1381  "ATTRCOND" => "attrcond$k",
1382  "FUNCCOND" => "funccond$k",
1383  "ISENUM" => (($keyId == "state") || ($keyId == "fixstate") || ($keyId == "activity") || ($oa && $oa->type == "enum")) ,
1384  "SSTATE" => "sstate$k",
1385  "ols_and_selected" => ($tol[$k] == "and") ? "selected" : "",
1386  "ols_or_selected" => ($tol[$k] == "or") ? "selected" : "",
1387  "leftp_none_selected" => ($tlp[$k] != "yes") ? "selected" : "",
1388  "leftp_open_selected" => ($tlp[$k] == "yes") ? "selected" : "",
1389  "rightp_none_selected" => ($trp[$k] != "yes") ? "selected" : "",
1390  "rightp_open_selected" => ($trp[$k] == "yes") ? "selected" : "",
1391  "key" => $v,
1392  "rowidx" => $k
1393  );
1394  $tattrSelect = array();
1395  if ($keyId == "state" || ($keyId == "fixstate") || ($keyId == "activity")) {
1396  $tstates = array();
1397  $stateselected = false;
1398  foreach ($states as $ks => $vs) {
1399  if ($keyId != "activity") {
1400  $tstates[] = array(
1401  "sstateid" => $vs,
1402  "sstep" => "state",
1403  "sstate_selected" => ($vs == $v) ? "selected" : "",
1404  "sstatename" => _($vs)
1405  );
1406  } else {
1407  $activity = $wdoc->getActivity($vs);
1408  $tstates[] = array(
1409  "sstateid" => $vs,
1410  "sstep" => "activity",
1411  "sstate_selected" => ($vs == $v) ? "selected" : "",
1412  "sstatename" => ($activity) ? _($activity) : _($vs)
1413  );
1414  }
1415  if ($vs == $v) $stateselected = true;
1416  }
1417  if (!$stateselected) $tcond[$k]["ISENUM"] = false;
1418  $this->lay->SetBlockData("sstate$k", $tstates);
1419 
1420  $tattrSelect[] = array(
1421  "attrid" => $keyId,
1422  "ismultiple" => 'no',
1423  "attrtype" => "enum",
1424  "attrdisabled" => '',
1425  "attrselected" => "selected",
1426  "attrname" => _($keyId)
1427  );
1428  } else {
1429  if ($oa && $oa->type == "enum") {
1430  /**
1431  * @var \NormalAttribute $oa
1432  */
1433  $te = $oa->getEnum();
1434  $tstates = array();
1435  $enumselected = false;
1436  foreach ($te as $ks => $vs) {
1437  $tstates[] = array(
1438  "sstateid" => $ks,
1439  "sstate_selected" => ($ks == $v) ? "selected" : "",
1440  "sstatename" => $vs
1441  );
1442  if ($ks == $v) $enumselected = true;
1443  }
1444  $this->lay->SetBlockData("sstate$k", $tstates);
1445  if (!$enumselected) $tcond[$k]["ISENUM"] = false;
1446  }
1447 
1448  $tattrSelect = $tattr;
1449  foreach ($tattrSelect as $ki => $vi) {
1450  $tattrSelect[$ki]["attrselected"] = "";
1451  }
1452 
1453  foreach ($internals as $ki => $vi) {
1454  if (isset($tattrSelect[$ki])) {
1455  $tattrSelect[$ki]["attrselected"] = ($keyId == $ki) ? "selected" : "";
1456  }
1457  }
1458 
1459  $this->editGetSetAttribute(null, true);
1460  foreach ($zpi as $ki => $vi) {
1461  if (isset($tattrSelect[$ki])) {
1462  $tattrSelect[$vi->id]["attrselected"] = ($keyId == $vi->id) ? "selected" : "";
1463  }
1464  }
1465  }
1466  $this->lay->SetBlockData("attrcond$k", $tattrSelect);
1467 
1468  $tfunc = array();
1469  foreach ($this->top as $ki => $vi) {
1470  $oa = $fdoc->getAttribute($keyId);
1471  if ($oa) $type = $oa->type;
1472  else $type = '';
1473  if ($type == "") {
1474  if ($keyId == "title") $type = "text";
1475  elseif ($keyId == "cdate") $type = "date";
1476  elseif ($keyId == "fixstate") $type = "enum";
1477  elseif ($keyId == "activity") $type = "enum";
1478  elseif ($keyId == "revision") $type = "int";
1479  elseif ($keyId == "allocated") $type = "uid";
1480  elseif ($keyId == "locked") $type = "uid";
1481  elseif ($keyId == "revdate") $type = "date";
1482  elseif ($keyId == "owner") $type = "uid";
1483  elseif ($keyId == "svalues") $type = "text";
1484  elseif ($keyId == "state") $type = "enum";
1485  } else {
1486  if (($oa->isMultiple() || $oa->inArray()) && $type === "docid") $type = "docid[]";
1487  else if (($oa->isMultiple() || $oa->inArray()) && $type === "account") $type = "account[]";
1488  else if ($oa->inArray() && ($oa->type != 'file')) $type = "array";
1489  }
1490  $display = '';
1491  $ctype = '';
1492  if (isset($vi["type"])) {
1493  if (!in_array($type, $vi["type"])) $display = 'none';
1494  $ctype = implode(",", $vi["type"]);
1495  }
1496  if ($tf[$k] == $ki && $display == '' && ((($type == 'docid' || $type == 'account') && ($ki == '=' || $ki == '!=')) || (($type == 'docid[]' || $type == 'account[]') && $ki == '~y'))) {
1497  $docid_aid = $keyId;
1498  }
1499  $tfunc[] = array(
1500  "func_id" => $ki,
1501  "func_selected" => ($tf[$k] == $ki) ? "selected" : "",
1502  "func_display" => $display,
1503  "func_type" => $ctype,
1504  "func_name" => $this->getOperatorLabel($ki, $type)
1505  );
1506  }
1507 
1508  $this->lay->SetBlockData("funccond$k", $tfunc);
1509 
1510  $tols = array();
1511  foreach ($this->tol as $ki => $vi) {
1512  $tols[] = array(
1513  "ol_id" => $ki,
1514  "ol_selected" => ($tol[$k] == $ki) ? "selected" : "",
1515  "ol_name" => _($vi)
1516  );
1517  }
1518  $this->lay->SetBlockData("olcond$k", $tols);
1519 
1520  if ((is_numeric($v) || empty($v)) && isset($docid_aid) && !empty($docid_aid)) {
1521  $tcond[$k]["ISENUM"] = false;
1522  $tcond[$k]["ISDOCID"] = true;
1523  $tcond[$k]["ISDOCIDMULTIPLE"] = $oa->isMultiple();
1524  $tcond[$k]["DOCID_AID"] = $docid_aid;
1525  $tcond[$k]["DOCID_AIDINDEX"] = $docid_aid . $k;
1526  $tcond[$k]["DOCID_TITLE"] = $this->getTitle($v);
1527  $tcond[$k]["FAMID"] = abs($famid);
1528  $tcond[$k]["ISSEARCHMETHOD"] = false;
1529  } else {
1530  $tcond[$k]["ISDOCID"] = false;
1531  $tcond[$k]["ISDOCIDMULTIPLE"] = false;
1532  $tcond[$k]["DOCID_AID"] = 0;
1533  $tcond[$k]["DOCID_AIDINDEX"] = 0;
1534  $tcond[$k]["DOCID_TITLE"] = '';
1535  $tcond[$k]["FAMID"] = abs($famid);
1536  $isSearchMethod = false;
1537  if ($oa) {
1538  $attrType = $oa->type;
1539  if ($oa->format != '') {
1540  // Recompose full attr spec: <attrType>("<format>")
1541  $attrType = sprintf('%s("%s")', $attrType, $oa->format);
1542  }
1543  $methods = $tmpDoc->getSearchMethods($oa->id, $attrType);
1544 
1545  foreach ($methods as $method) {
1546  if ($method['method'] == $v) {
1547  $isSearchMethod = true;
1548  break;
1549  }
1550  }
1551  }
1552  $tcond[$k]["ISSEARCHMETHOD"] = $isSearchMethod;
1553  }
1554  }
1555  }
1556  if (count($tcond) > 0) $this->lay->SetBlockData("CONDITIONS", $tcond);
1557  // Add select for enum attributes
1558  $tenums = array();
1559  foreach ($zpi as $k => $v) {
1560  if (($v->type == "enum") || ($v->type == "enumlist")) {
1561  $tenums[] = array(
1562  "SELENUM" => "ENUM$k",
1563  "attrid" => $v->id
1564  );
1565  $tenum = $v->getEnum();
1566  $te = array();
1567  foreach ($tenum as $ke => $ve) {
1568  if ($ke === ' ' || $ke === '') {
1569  continue;
1570  }
1571  $te[] = array(
1572  "enumkey" => $ke,
1573  "enumlabel" => $ve
1574  );
1575  }
1576  $this->lay->setBlockData("ENUM$k", $te);
1577  }
1578  }
1579 
1580  $this->lay->setBlockData("ENUMS", $tenums);
1581 
1582  $this->lay->Set("id", $this->id);
1583  $this->editattr();
1584  }
1585  /**
1586  * @param \BasicAttribute $fs
1587  * @param bool $reset
1588  * @return array
1589  */
1590  private function editGetSetAttribute($fs, $reset = false)
1591  {
1592  static $setAttribute = array();
1593  $level = 0;
1594  $tset = array();
1595  if ($reset) $setAttribute = array();
1596  while ($fs && $fs->id != \Adoc::HIDDENFIELD) {
1597  if (!in_array($fs->id, $setAttribute)) {
1598  $tset[$fs->id] = array(
1599  "attrid" => $fs->id,
1600  "attrtype" => "set",
1601  "attrdisabled" => "disabled",
1602  "attrselected" => "",
1603  "attrname" => $fs->getLabel()
1604  );
1605  $setAttribute[] = $fs->id;
1606  $level++;
1607  $fs = $fs->fieldSet;
1608  } else {
1609  break;
1610  }
1611  }
1612  return $tset;
1613  }
1614 
1615  private function getMethodName($methodStr)
1616  {
1617  $parseMethod = new \parseFamilyMethod();
1618  $parseMethod->parse($methodStr);
1619  $err = $parseMethod->getError();
1620  if ($err) {
1621  return '';
1622  }
1623  return $parseMethod->methodName;
1624  }
1625 
1626  public static function pgRegexpQuote($str)
1627  {
1628  /*
1629  * Escape Postgresql's regexp special chars into theirs UTF16 form "\u00xx"
1630  */
1631  return preg_replace_callback('/[.|*+?{}\[\]()\\\\^$]/u', function ($m)
1632  {
1633  return sprintf('\\u00%x', ord($m[0]));
1634  }
1635  , $str);
1636  }
1637 }
preEdition()
Definition: Class.Doc.php:2934
static $infofields
Definition: Class.Doc.php:105
ComputeQuery($keyword="", $famid=-1, $latest="yes", $sensitive=false, $dirid=-1, $subfolder=true, $full=false)
$s type
Definition: dav.php:73
$tdoc
global $action
& getAttribute($idAttr, &$oa=null, $useMask=true)
Definition: Class.Doc.php:2152
static getDate($daydelta=0, $dayhour="", $daymin="", $getlocale=false)
Definition: Class.Doc.php:8783
stringDateToIso($date, $format=false, $withT=false)
Definition: Lib.Util.php:246
getSqlSearchDoc($dbaccess, $dirid, $fromid, $sqlfilters=array(), $distinct=false, $latest=true, $trash="", $simplesearch=false, $folderRecursiveLevel=2, $join= '', $only="")
Definition: Lib.Dir.php:108
viewdsearch($target="_self", $ulink=true, $abstract=false)
$full
static rawValueToArray($v)
Definition: Class.Doc.php:6228
getDbAccessCore()
Definition: Lib.Common.php:373
$sensitive
addWarningMsg($msg)
Definition: Lib.Common.php:95
getIcon($idicon="", $size=null, $otherId=null)
Definition: Class.Doc.php:5817
if($famId) $s
viewattr($target="_self", $ulink=true, $abstract=false, $viewhidden=false)
Definition: Class.Doc.php:7695
getLocaleConfig($core_lang= '')
Definition: Lib.Common.php:853
simpleXml2StdClass(\SimpleXMLElement $xml)
equal($a, $b)
Definition: Class.Doc.php:2777
getSqlGeneralFilters($keyword, $latest, $sensitive, $full=false)
getOperatorLabel($operator, $attributeType)
savePoint($point)
modify($nopost=false, $sfields="", $nopre=false)
editattr($withtd=true)
Definition: Class.Doc.php:8129
GetClassesDoc($dbaccess, $userid, $classid=0, $qtype="LIST", $extraFilters=array())
Definition: Lib.Dir.php:906
if($real||$full) else
isChanged()
Definition: Class.Doc.php:853
getHtmlInput(&$doc, &$oattr, $value, $index="", $jsevent="", $notd=false)
Definition: editutil.php:30
setValue($attrid, $value, $index=-1, &$kvalue=null)
Definition: Class.Doc.php:3528
setFamidInLayout()
Definition: Class.Doc.php:8157
getMultipleRawValues($idAttr, $def="", $index=-1)
Definition: Class.Doc.php:3240
revision(Action &$action)
Definition: revision.php:22
getHttpVars($name, $def="", $scope="all")
Definition: Lib.Http.php:124
if($updateExistingTable) $point
Definition: updateclass.php:88
getFamIdFromName($dbaccess, $name)
object2SqlFilter($of, &$famid, &$fsql)
mb_ucfirst($s)
Definition: Lib.Common.php:105
getTitle($id="-1", $def="", $latest=false)
Definition: Class.Doc.php:8715
getRChildDirId($dbaccess, $dirid, $rchilds=array(), $level=0, $levelmax=2)
Definition: Lib.Dir.php:822
deprecatedFunction($msg= '')
Definition: Lib.Common.php:86
rollbackPoint($point)
new_Doc($dbaccess, $id= '', $latest=false)
$dir
Definition: resizeimg.php:144
$keyword
editmode(Action &$action)
Definition: editutil.php:41
unaccent($s)
Definition: Lib.Util.php:569
if(($docid!==0)&&(!is_numeric($docid))) $query
getIdFromName($dbaccess, $name)
simpleQuery($dbaccess, $query, &$result=array(), $singlecolumn=false, $singleresult=false, $useStrict=null)
Definition: Lib.Common.php:484
createTmpDoc($dbaccess, $fromid, $defaultvalue=true)
if($file) if($subject==""&&$file) if($subject=="") $err
getRawValue($idAttr, $def="")
Definition: Class.Doc.php:3117
paramdsearch($target="_self", $ulink=true, $abstract=false)
N_($s)
Definition: Lib.Common.php:18
$latest
$value
getSqlDetailFilter($validateCond=false)
isValidCondition($attr, $op, $value)
← centre documentaire © anakeen