Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.FamilyImport.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Generation of PHP Document classes
8  *
9  * @author Anakeen
10  * @package FDL
11  * @subpackage
12  */
13 /**
14  */
15 
16 namespace Dcp;
17 
19 {
20  /**
21  * Write PHP content to destination file if PHP syntax is correct.
22  *
23  * - The content is first written to a temporary file next to the
24  * final destination file.
25  * - The syntax of the temporary file is checked.
26  * - If the syntax is correct, then the temporary file is "commited"
27  * to the destination file.
28  *
29  * @param string $fileName destination file
30  * @param string $content content to write
31  *
32  * @return string empty string on success or error message on failure
33  */
34  protected static function __phpLintWriteFile($fileName, $content)
35  {
36  $dir = dirname($fileName);
37  $temp = tempnam($dir, basename($fileName) . '.tmp');
38  if ($temp === false) {
39  return sprintf(_("Error creating temporary file in '%s'.") , $dir);
40  }
41  if (file_put_contents($temp, $content) === false) {
42  unlink($temp);
43  return sprintf(_("Error writing content to file '%s'.") , $temp);
44  }
45  if (\CheckClass::phpLintFile($temp, $output) === false) {
46  // Leave temp file for syntax error analysis
47  return sprintf(_("Syntax error in file '%s': %s") , $temp, join("\n", $output));
48  }
49  if (rename($temp, $fileName) === false) {
50  unlink($temp);
51  return sprintf(_("Error renaming '%s' to '%s'.") , $temp, $fileName);
52  }
53  return '';
54  }
55  /**
56  * Generate Class.Docxxx.php files
57  *
58  * @param string $dbaccess database specification
59  * @param array $tdoc array of family definition
60  *
61  * @return string
62  * @throws Db\Exception
63  * @throws Exception
64  */
65  protected static function generateFamilyPhpClass($dbaccess, $tdoc)
66  {
67  global $action;
68 
69  $GEN = getGen($dbaccess);
70  $phpAdoc = new \Layout("FDL/Layout/Class.Doc.xml", $action);
71 
72  if ($tdoc["classname"] == "") { // default classname
73  if ($tdoc["fromid"] == 0) {
74  $tdoc["classname"] = '\Dcp\Family\Document';
75  } else {
76  $tdoc["classname"] = "Doc" . $tdoc["fromid"];
77  }
78  } else {
79  $tdoc["classname"] = '\\' . $tdoc["classname"];
80  }
81  if ($tdoc["fromid"] > 0) {
82  $fromName = getNameFromId($dbaccess, $tdoc["fromid"]);
83  if ($fromName == '') {
84  throw new \Dcp\Exception("FAM0601", $tdoc["fromid"], $tdoc["name"]);
85  }
86  $tdoc["fromname"] = $fromName;
87  } else {
88  $tdoc["fromname"] = "Document";
89  }
90  $phpAdoc->Set("docid", $tdoc["id"]);
91  $phpAdoc->Set("include", "");
92  $phpAdoc->Set("GEN", "");
93  if ($tdoc["fromid"] == 0) {
94  $phpAdoc->Set("DocParent", $tdoc["classname"]);
95  $phpAdoc->Set("AParent", "ADoc");
96  $phpAdoc->Set("fromid", "");
97  $phpAdoc->Set("pinit", '\DocCtrl');
98  } else {
99  $parentFile = sprintf("%s/FDLGEN/Class.Doc%d.php", DEFAULT_PUBDIR, $tdoc["fromid"]);
100  if ((!file_exists($parentFile)) || filesize($parentFile) == 0) {
101  throw new \Dcp\Exception("FAM0600", $parentFile, $tdoc["name"]);
102  }
103  $phpAdoc->Set("fromid", $tdoc["fromid"]);
104  if ($tdoc["classname"] != "Doc" . $tdoc["fromid"]) {
105  $phpAdoc->Set("DocParent", $tdoc["classname"]);
106  $phpAdoc->Set("pinit", $tdoc["classname"]);
107  $phpAdoc->Set("include", "include_once(\"FDL$GEN/Class.Doc" . $tdoc["fromid"] . ".php\");");
108  } else {
109  $phpAdoc->Set("GEN", $GEN);
110  if ($tdoc["name"]) {
111  $phpAdoc->Set("DocParent", '\\Dcp\\Family\\' . ucwords(strtolower($tdoc["fromname"])));
112  } else {
113  $phpAdoc->Set("DocParent", '\\Doc' . $tdoc["fromid"]);
114  }
115  $phpAdoc->Set("FileClassParent", 'Doc' . $tdoc["fromid"]);
116  if (strstr($tdoc["usefor"], 'W')) {
117  $phpAdoc->Set("pinit", '\WDoc');
118  } // special init for workflow
119  else {
120  $phpAdoc->Set("pinit", '\DocCtrl');
121  }
122  }
123  $phpAdoc->Set("AParent", "ADoc" . $tdoc["fromid"]);
124  }
125  $phpAdoc->Set("title", $tdoc["title"]);
126  $query = new \QueryDb($dbaccess, "DocAttr");
127  $query->AddQuery("docid=" . $tdoc["id"]);
128  $query->order_by = "ordered";
129 
130  $docDbAttrs = $query->Query();
131 
132  $phpAdoc->Set("sattr", "");
133 
134  $phpAdoc->set("hasattr", false);
135  $pa = self::getParentAttributes($dbaccess, $tdoc["fromid"]);
136  $allAttributes = [];
137  if ($query->nb > 0) {
138 
139  $tmenu = array();
140  $tfield = array();
141  $tnormal = array();
142  $tattr = array();
143  $attrids = array();
144  $tcattr = array();
145  $taction = array();
146  /**
147  * @var $v \DocAttr
148  */
149  $table1 = [];
150  foreach ($docDbAttrs as $k => $v) {
151  $table1[strtolower($v->id) ] = $v;
152  }
153 
154  foreach ($table1 as $k => $v) {
155  $type = trim(strtok($v->type, "("));
156  if ($type === "docid" || $type == "account" || $type == "thesaurus") {
157  $parentDoctitle = "";
158  if (isset($pa[substr($v->id, 1) ]) && preg_match("/doctitle=([A-Za-z0-9_-]+)/", $pa[substr($v->id, 1) ]["options"], $reg)) {
159  $parentDoctitle = $reg[1];
160  }
161  // add title auto
162  if ($v->usefor !== 'Q' && preg_match("/doctitle=([A-Za-z0-9_-]+)/", $v->options, $reg)) {
163  $doctitle = $reg[1];
164  if ($doctitle === $parentDoctitle) {
165  continue;
166  }
167  if ($doctitle == "auto") {
168  $doctitle = $v->id . "_title";
169  }
170  $doctitle = strtolower($doctitle);
171  if (!isset($table1[strtolower($doctitle) ])) {
172  $table1[$doctitle] = clone ($v);
173  $table1[$doctitle]->id = $doctitle;
174  $table1[$doctitle]->type = "text";
175  $table1[$doctitle]->visibility = "H";
176  $table1[$doctitle]->phpfile = "";
177 
178  $table1[$doctitle]->options = "autotitle=yes|relativeOrder=" . $v->id;
179  $table1[$doctitle]->title = "N";
180  $table1[$doctitle]->abstract = "N";
181  $table1[$doctitle]->needed = "N";
182  $table1[$doctitle]->usefor = "A";
183  $table1[$doctitle]->link = "";
184  $table1[$doctitle]->phpconstraint = "";
185  $table1[$doctitle]->labeltext = $v->labeltext . ' ' . _("(title)");
186  $table1[$doctitle]->ordered = $v->ordered + 1;
187  }
188  if (empty($table1[$doctitle]->phpfunc)) {
189  if (!preg_match("/docrev=(fixed|state)/", $v->options)) {
190  $table1[$doctitle]->phpfunc = "::getLastTitle(" . $v->id . ",' )";
191  } else {
192  $table1[$doctitle]->phpfunc = "::getTitle(" . $v->id . ",' )";
193  }
194  }
195  }
196  }
197  }
198  $pM = new \parseFamilyMethod();
199 
200  foreach ($pa as $parentAttr) {
201  $previousOrder = ""; //FamilyAbsoluteOrder::autoOrder;
202  if (preg_match("/relativeOrder=([A-Za-z0-9_:-]+)/", $parentAttr["options"], $reg)) {
203  $previousOrder = strtolower($reg[1]);
204  }
205  if ($parentAttr["id"][0] !== ":") {
206  $allAttributes[$parentAttr["id"] . "/" . $parentAttr["docid"]] = ["id" => $parentAttr["id"], "parent" => $parentAttr["frameid"], "family" => $parentAttr["docid"], "prev" => $previousOrder, "numOrder" => intval($parentAttr["ordered"]) ];
207  if (!$previousOrder) {
208  // Need to copy child attribute when use absolute orders
209  $allAttributes[$parentAttr["id"] . "/" . $tdoc["id"]] = $allAttributes[$parentAttr["id"] . "/" . $parentAttr["docid"]];
210  $allAttributes[$parentAttr["id"] . "/" . $tdoc["id"]]["family"] = $tdoc["id"];
211  }
212  } else {
213  if (is_numeric($parentAttr["ordered"])) {
214  $pattern = sprintf("/%s\\/([0-9]+)/", substr($parentAttr["id"], 1));
215 
216  foreach ($allAttributes as $ka => $attrData) {
217  if (preg_match($pattern, $ka, $reg)) {
218  // Need to update parent also
219  if ($parentAttr["frameid"]) {
220  $allAttributes[$ka]["parent"] = $parentAttr["frameid"];
221  }
222  $allAttributes[$ka]["numOrder"] = $parentAttr["ordered"];
223  }
224  }
225  }
226  }
227  }
228 
229  foreach ($table1 as $k => $v) {
230  $validOrder = true;
231  if ($v->id[0] === ':') {
232  if (!$v->ordered && !$v->frameid) {
233  $validOrder = false;
234  }
235  $v = self::completeAttribute($dbaccess, $v);
236  if (is_numeric($v->ordered)) {
237  $pattern = sprintf("/%s\\/([0-9]+)/", $v->id);
238  foreach ($allAttributes as $ka => $attrData) {
239  if (preg_match($pattern, $ka, $reg)) {
240  if ($v->frameid) {
241  $allAttributes[$ka]["parent"] = $v->frameid;
242  }
243  $allAttributes[$ka]["numOrder"] = $v->ordered;
244  }
245  }
246  }
247  }
248 
249  $previous = ""; //FamilyAbsoluteOrder::autoOrder;
250  if (preg_match("/relativeOrder=([A-Za-z0-9_:-]+)/", $v->options, $reg)) {
251  $previous = strtolower($reg[1]);
252  }
253  if ($validOrder) {
254  $allAttributes[$v->id . "/" . $v->docid] = ["id" => $v->id, "parent" => $v->frameid, "family" => $v->docid, "prev" => $previous, "numOrder" => intval($v->ordered) ];
255  }
256  if ($v->visibility == "F") {
257  $v->type = "frame";
258  } // old notation compliant
259  elseif ($v->visibility == "M") {
260  $v->type = "menu";
261  } // old notation compliant
262  if ($v->type == "integer") {
263  $v->type = "int";
264  } // old notation compliant
265  //$v->phpfunc = str_replace("\"", "\\\"", $v->phpfunc);
266  switch (strtolower($v->type)) {
267  case "menu": // menu
268  if (substr($v->link, 0, 2) == "::") {
269  if (preg_match('/::([^\(]+)\(([^\)]*)\)/', $v->link, $reg)) {
270  $v->link = "%S%app=FDL&action=FDL_METHOD&id=%I%&method=" . urlencode($v->link);
271  }
272  }
273  $tmenu[strtolower($v->id) ] = array(
274  "attrid" => strtolower($v->id) ,
275  "label" => str_replace("\"", "\\\"", $v->labeltext) ,
276  "order" => intval($v->ordered) ,
277  "link" => str_replace("\"", "\\\"", $v->link) ,
278  "visibility" => $v->visibility,
279  "options" => str_replace("\"", "\\\"", $v->options) ,
280  "precond" => self::doubleslash($v->phpfunc)
281  );
282  break;
283 
284  case "tab":
285  case "frame": // frame
286  $tfield[strtolower($v->id) ] = array(
287  "attrid" => strtolower($v->id) ,
288  "visibility" => $v->visibility,
289  "label" => str_replace("\"", "\\\"", $v->labeltext) ,
290  "usefor" => $v->usefor,
291  "type" => $v->type,
292  "options" => str_replace("\"", "\\\"", $v->options) ,
293  "frame" => ($v->frameid == "") ? \Adoc::HIDDENFIELD : strtolower($v->frameid)
294  );
295  break;
296 
297  case "action": // action
298  $taction[strtolower($v->id) ] = array(
299  "attrid" => strtolower($v->id) ,
300  "visibility" => $v->visibility,
301  "label" => str_replace("\"", "\\\"", $v->labeltext) ,
302  "order" => intval($v->ordered) ,
303  "options" => str_replace("\"", "\\\"", $v->options) ,
304  "wapplication" => $v->phpfile,
305  "waction" => self::doubleslash($v->phpfunc) ,
306  "precond" => str_replace("\"", "\\\"", $v->phpconstraint)
307  );
308  break;
309 
310  default: // normal
311  if (preg_match('/^\[([a-z=0-9]+)\](.*)/', $v->phpfunc, $reg)) {
312  $v->phpfunc = $reg[2];
313  $funcformat = $reg[1];
314  } else {
315  $funcformat = "";
316  }
317 
318  if (preg_match("/([a-z]+)\\([\"'](.*)[\"']\\)/i", $v->type, $reg)) {
319  $atype = $reg[1];
320  $aformat = $reg[2];
321  if ($atype == "idoc") {
322  if (!is_numeric($aformat)) {
323  $aformat = getFamIdFromName($dbaccess, $aformat);
324  }
325  }
326  } else {
327  $atype = $v->type;
328  $aformat = "";
329  }
330  $repeat = "false";
331  if (preg_match("/([a-z]+)list/i", $atype, $reg)) {
332  $atype = $reg[1];
333  $repeat = "true";
334  } else {
335  if (strpos($v->options, "multiple=yes") !== false) {
336  $repeat = "true";
337  } else {
338  if (isset($tnormal[strtolower($v->frameid) ])) {
339  if (self::getTypeMain($tnormal[strtolower($v->frameid) ]["type"]) == "array") {
340  $repeat = "true";
341  }
342  }
343 
344  if (($repeat == "false") && isset($pa[strtolower($v->frameid) ])) {
345  if (self::getTypeMain($pa[strtolower($v->frameid) ]["type"]) == "array") {
346  $repeat = "true";
347  }
348  }
349  }
350  }
351 
352  $atype = strtolower(trim($atype));
353  // create code for calculated attributes
354  if ((!$v->phpfile) && preg_match('/^(?:(?:[a-z_][a-z0-9_]*\\\\)*[a-z_][a-z0-9_]*)?::[a-z_][a-z0-9_]*\(/i', $v->phpfunc, $reg) && ($v->usefor != 'Q')) {
355 
356  $pM->parse($v->phpfunc);
357  $error = $pM->getError();
358  if ($error) {
359  throw new \Dcp\Exception($error);
360  }
361  if (!$pM->outputString) {
362  $oAid = $v->id;
363  } else {
364  $oAid = $pM->outputs[0];
365  }
366  $tcattr[] = array(
367  "callmethod" => self::doubleslash($v->phpfunc) ,
368  "callattr" => $oAid
369  );
370  }
371  // complete attributes characteristics
372  $v->id = chop(strtolower($v->id));
373 
374  if (!$v->phpconstraint) {
375  if (($atype == "integer") || ($atype == "int")) {
376  $v->phpconstraint = sprintf("::isInteger(%s)", $v->id);
377  } elseif (($atype == "money") || ($atype == "double")) {
378  $v->phpconstraint = sprintf("::isFloat(%s)", $v->id);
379  }
380  }
381  if ($atype == "account") {
382  if (!$v->phpfile && !$v->phpfunc) {
383  $v->phpfile = 'fdl.php';
384  $options = $v->options;
385  if ($aformat) {
386  if ($options) {
387  $options.= '|';
388  }
389  $options.= sprintf("family=%s", $aformat);
390  }
391  $v->phpfunc = sprintf('fdlGetAccounts(CT,15,"%s"):%s,CT', str_replace('"', '\\"', $options) , $v->id);
392  }
393  }
394  $tnormal[($v->id) ] = array(
395  "attrid" => ($v->id) ,
396  "label" => str_replace("\"", "\\\"", $v->labeltext) ,
397  "type" => $atype,
398  "format" => str_replace("\"", "\\\"", $aformat) ,
399  "eformat" => str_replace("\"", "\\\"", $funcformat) ,
400  "options" => self::doubleslash($v->options) ,
401  //(str_replace("\"", "\\\"", $v->options) ,
402  "order" => intval($v->ordered) ,
403  "link" => str_replace("\"", "\\\"", $v->link) ,
404  "visibility" => $v->visibility,
405  "needed" => ($v->needed == "Y") ? "true" : "false",
406  "title" => ($v->title == "Y") ? "true" : "false",
407  "repeat" => $repeat,
408  "abstract" => ($v->abstract == "Y") ? "true" : "false",
409  "frame" => ($v->frameid == "") ? \Adoc::HIDDENFIELD : strtolower($v->frameid) ,
410  "elink" => $v->elink,
411  "phpfile" => $v->phpfile,
412  "phpfunc" => self::doubleslash(str_replace(", |", ", |", $v->phpfunc)) ,
413  "phpconstraint" => str_replace("\"", "\\\"", $v->phpconstraint) ,
414  "usefor" => $v->usefor
415  );
416 
417  if (($atype != "array") && ($v->usefor != "Q")) {
418  if ($atype != "array") {
419  $tattr[$v->id] = array(
420  "attrid" => ($v->id)
421  );
422  }
423  if ($repeat == "true") {
424  $attrids[$v->id] = ($v->id) . " text"; // for the moment all repeat are text
425 
426  } else {
427  switch ($atype) {
428  case 'double':
429  case 'float':
430  case 'money':
431  $attrids[$v->id] = ($v->id) . " float8";
432  break;
433 
434  case 'int':
435  case 'integer':
436  $attrids[$v->id] = ($v->id) . " int4";
437  break;
438 
439  case 'date':
440  $attrids[$v->id] = ($v->id) . " date";
441  break;
442 
443  case 'timestamp':
444  $attrids[$v->id] = ($v->id) . " timestamp without time zone";
445  break;
446 
447  case 'time':
448  $attrids[$v->id] = ($v->id) . " time";
449  break;
450 
451  default:
452  $attrids[$v->id] = ($v->id) . " text";
453  }
454  }
455  }
456  }
457  }
458 
459  FamilyAbsoluteOrder::completeForNumericOrder($allAttributes, $tdoc["id"]);
460 
461  $absoluteOrders = FamilyAbsoluteOrder::getAbsoluteOrders($allAttributes, $tdoc["id"]);
462  $tAbsOrders = [];
463  foreach ($absoluteOrders as $kOrder => $attrid) {
464  $tAbsOrders[] = sprintf('"%s"=>%d', $attrid, ($kOrder + 1) * 10);
465  }
466  $phpAdoc->Set("sattr", implode(",", $attrids));
467  $phpAdoc->Set("sAbsoluteOrders", implode(",", $tAbsOrders));
468  $phpAdoc->SetBlockData("MATTR", $tmenu);
469  $phpAdoc->SetBlockData("FATTR", $tfield);
470  $phpAdoc->SetBlockData("AATTR", $taction);
471  $phpAdoc->SetBlockData("NATTR", $tnormal);
472  $phpAdoc->SetBlockData("ATTRFIELD", $tattr);
473 
474  $phpAdoc->set("hasattr", (count($tattr) > 0));
475  $phpAdoc->SetBlockData("ACALC", $tcattr);
476  } else {
477  $phpAdoc->Set("sAbsoluteOrders", "");
478  }
479 
480  $phpAdoc->Set("STARMETHOD", false);
481  if ($tdoc["name"] == '') {
482  $tdoc["name"] = 'F__' . $tdoc["id"];
483  }
484  if ($tdoc["name"] != "") { // create name alias classes
485  $phpAdoc->SetBlockData("CLASSALIAS", array(
486  array(
487  "zou"
488  )
489  ));
490  $phpAdoc->Set("docName", $tdoc["name"]);
491  $phpAdoc->Set("PHPclassName", sprintf('%s', str_replace(array(
492  ":",
493  "-"
494  ) , "_", ucwords(strtolower($tdoc["name"])))));
495  }
496  $phpAdoc->Set("docTitle", str_replace('"', '\\"', $tdoc["title"]));
497  $phpAdoc->set("HOOKALIAS", "");
498  //----------------------------------
499  // Add specials methods
500  $cmethod = ""; // method file which is use as inherit virtual class
501  $contents = '';
502  $contents2 = '';
503  $hasMethod = false;
504  if (isset($tdoc["methods"]) && ($tdoc["methods"] != "")) {
505  $tfmethods = explode("\n", $tdoc["methods"]);
506  foreach ($tfmethods as $fmethods) {
507  if ($fmethods[0] == "*") {
508  $cmethod = substr($fmethods, 1);
509  $filename = DEFAULT_PUBDIR . "/FDL/" . $cmethod;
510  $contents2 = self::getMethodFileInnerContents($filename);
511  /* Skip empty method file */
512  if (strlen(trim($contents2)) <= 0) {
513  $cmethod = '';
514  $contents2 = '';
515  }
516  } else {
517  $filename = DEFAULT_PUBDIR . "/FDL/" . $fmethods;
518  $innerContents = self::getMethodFileInnerContents($filename);
519  /* Concatenate non-empty method file */
520  if (strlen(trim($innerContents)) > 0) {
521  $contents.= $innerContents;
522  $hasMethod = true;
523  }
524  }
525  }
526  }
527  if ($hasMethod) {
528  $dm = new \deprecatedHookManager();
529  $dm->inspectContent("<?php\n" . $contents . "\n?>");
530  $phpAdoc->set("HOOKALIAS", $dm->generateCompatibleMethods());
531  $phpAdoc->Set("METHODS", $contents);
532  $phpMethodName = sprintf("_Method_%s", $tdoc["name"]);
533  $phpAdoc->set("PHPmethodName", $phpMethodName);
534  $phpAdoc->set("ClassDocParent", $phpAdoc->Get("DocParent"));
535  $phpAdoc->set("DocParent", '\\' . $phpMethodName);
536  } else {
537  $phpAdoc->Set("METHODS", "");
538  }
539 
540  if ($cmethod != "") {
541  $phpAdoc->Set("METHODS2", $contents2);
542  $phpAdoc->Set("STARMETHOD", true);
543  $phpAdoc->Set("docNameIndirect", '_SMethod_Doc' . $tdoc["id"] . "__");
544  if ($hasMethod) {
545 
546  $phpAdoc->Set("RedirectDocParent", $phpAdoc->Get("ClassDocParent"));
547  $phpAdoc->Set("ClassDocParent", '\\' . $phpAdoc->Get("docNameIndirect"));
548  } else {
549  $phpAdoc->Set("RedirectDocParent", $phpAdoc->Get("DocParent"));
550  $phpAdoc->Set("DocParent", '\\' . $phpAdoc->Get("docNameIndirect"));
551  }
552  }
553  return $phpAdoc->gen();
554  }
555 
556  protected static function AttrIdToPhp($dbaccess, $tdoc)
557  {
558  $phpAdoc = new \Layout("FDL/Layout/Class.Attrid.xml");
559 
560  if ($tdoc["fromid"] == 0) {
561  $phpAdoc->Set("extend", '');
562  } else {
563  $fromName = getNameFromId($dbaccess, $tdoc["fromid"]);
564  if ($fromName == '') {
565  throw new \Dcp\Exception("FAM0602", $tdoc["fromid"], $tdoc["name"]);
566  }
567  $phpAdoc->Set("extend", ucwords(strtolower(str_replace(array(
568  ":",
569  "-"
570  ) , "_", $fromName))));
571  }
572 
573  $phpAdoc->Set("fromid", $tdoc["fromid"]);
574  $phpAdoc->Set("title", $tdoc["title"]);
575  $phpAdoc->Set("className", ucfirst(strtolower(str_replace(array(
576  ":",
577  "-"
578  ) , "_", $tdoc["name"]))));
579 
580  $query = new \QueryDb($dbaccess, "DocAttr");
581  $query->AddQuery(sprintf("docid=%d", $tdoc["id"]));
582  $query->AddQuery(sprintf("id !~ ':'"));
583  $query->order_by = "ordered";
584  $attrs = $query->Query(0, 0, "TABLE");
585 
586  if ($query->nb > 0) {
587  $const = array();
588  foreach ($attrs as $attr) {
589  $const[$attr["id"]] = array(
590  "attrid" => $attr["id"],
591  "type" => $attr["type"],
592  "label" => $attr["labeltext"],
593  "famName" => $tdoc["name"]
594  );
595  }
596 
597  $phpAdoc->SetBlockData("CONST", $const);
598  }
599 
600  return $phpAdoc->gen();
601  }
602 
603  protected static function doubleslash($s)
604  {
605  $s = str_replace('\\', '\\\\', $s);
606  $s = str_replace('"', '\\"', $s);
607  return $s;
608  }
609 
610  protected static function pgUpdateFamily($dbaccess, $docid, $docname = "")
611  {
612  $docname = strtolower($docname);
613  $msg = '';
614  /* Create family's table if not exists */
615  if (!self::tableExists($dbaccess, "public", "doc$docid")) {
616  $msg.= sprintf("Create table 'doc%d'\n", $docid);
617  self::createFamilyTable($dbaccess, $docid);
618 
619  if (self::tableExists($dbaccess, "public", "doc$docid")) {
620  /* Re-create family's view */
621  self::recreateFamilyView($dbaccess, $docname, $docid);
622  } else {
623  $msg.= sprintf("Could not create table 'doc%d'.\n", $docid);
624  }
625  }
626 
627  $pgatt = self::getTableColumns($dbaccess, "public", "doc$docid");
628  // -----------------------------
629  // add column attribute
630  $qattr = new \QueryDb($dbaccess, "DocAttr");
631  $qattr->AddQuery("docid=" . $docid);
632  $qattr->AddQuery("type != 'menu'");
633  $qattr->AddQuery("type != 'frame'");
634  $qattr->AddQuery("type != 'tab'");
635  $qattr->AddQuery("type != 'action'");
636  $qattr->AddQuery("id !~ '^:'");
637  // $qattr->AddQuery("type !~ '^array'"); // must be visible to know for child attributes
638  $qattr->AddQuery("visibility != 'M'");
639  $qattr->AddQuery("visibility != 'F'");
640  $qattr->AddQuery("usefor != 'Q' or usefor is null");
641 
642  $oattr = $qattr->Query();
643  /**
644  * @var \DocAttr[] $tattr
645  */
646  $tattr = array();
647  if ($qattr->nb > 0) {
648  /**
649  * @var \DocAttr $attr
650  */
651  foreach ($oattr as $ka => $attr) {
652  $tattr[strtolower($attr->id) ] = $attr;
653  if ($attr->type == 'file') {
654  $tattr[strtolower($attr->id) . '_txt'] = $attr;
655  $tattr[strtolower($attr->id) . '_vec'] = clone ($attr);
656  $tattr[strtolower($attr->id) . '_vec']->type = 'tsvector';
657  } else {
658  $type = trim(strtok($attr->type, "("));
659  if ($type === "docid" || $type === "account" || $type === "thesaurus") {
660  if ($attr->usefor !== "Q" && preg_match("/doctitle=([A-Za-z0-9_-]+)/", $attr->options, $reg)) {
661  $doctitle = $reg[1];
662  if ($doctitle == "auto") {
663  $doctitle = $attr->id . "_title";
664  }
665  $doctitle = strtolower($doctitle);
666  $tattr[$doctitle] = $attr;
667  $tattr[$doctitle]->id = $doctitle;
668  $tattr[$doctitle]->type = "text";
669  }
670  }
671  }
672  }
673 
674  $updateView = false;
675  foreach ($tattr as $ka => $attr) {
676  $attr->id = chop($attr->id);
677  if (substr($attr->type, 0, 5) == "array") {
678  continue;
679  } // skip array but must be in table to search element in arrays
680  if ($attr->docid == $docid) { // modify my field not inherited fields
681  if (!in_array($ka, $pgatt)) {
682  $msg.= "add field $ka in table doc" . $docid . "\n";
683  $repeat = (strpos($attr->options, "multiple=yes") !== false);
684  if (!$repeat) {
685  $repeat = (isset($tattr[$attr->frameid]) && $tattr[$attr->frameid]->type == "array");
686  }
687  if (($repeat && ($attr->type != 'tsvector'))) {
688 
689  $sqltype = " text"; // for the moment all repeat are text
690 
691  } else {
692  $rtype = strtok($attr->type, "(");
693  switch ($rtype) {
694  case 'double':
695  case 'float':
696  case 'money':
697  $sqltype = " float8";
698  break;
699 
700  case 'int':
701  case 'integer':
702  $sqltype = " int4";
703  break;
704 
705  case 'date':
706  $sqltype = " date";
707  break;
708 
709  case 'timestamp':
710  $sqltype = " timestamp without time zone";
711  break;
712 
713  case 'time':
714  $sqltype = " time";
715  break;
716 
717  case 'tsvector':
718  $sqltype = " tsvector";
719  break;
720 
721  default:
722  $sqltype = " text";
723  }
724  }
725  self::alterTableAddColumn($dbaccess, "public", "doc$docid", $ka, $sqltype);
726  $updateView = true;
727  }
728  }
729  }
730  /* Update family's view if table structure has changed */
731  if ($updateView) {
732  self::recreateFamilyView($dbaccess, $docname, $docid);
733  }
734  }
735  return $msg;
736  }
737 
738  protected static function tableExists($dbaccess, $schemaName, $tableName)
739  {
740  simpleQuery($dbaccess, sprintf("SELECT 'true' FROM information_schema.tables WHERE table_schema = %s AND table_name = %s", pg_escape_literal($schemaName) , pg_escape_literal($tableName)) , $res, true, true, true);
741  return ($res == 'true');
742  }
743 
744  protected static function viewExists($dbaccess, $schemaName, $viewName)
745  {
746  simpleQuery($dbaccess, sprintf("SELECT 'true' FROM information_schema.views WHERE table_schema = %s AND table_name = %s", pg_escape_literal($schemaName) , pg_escape_literal($viewName)) , $res, true, true, true);
747  return ($res == 'true');
748  }
749 
750  protected static function createFamilyTable($dbaccess, $docid)
751  {
752  // create postgres table if new \familly
753  $cdoc = createTmpDoc($dbaccess, $docid, false);
754  $triggers = $cdoc->sqltrigger(false, true);
755  $cdoc->exec_query($triggers, 1);
756  // step by step
757  $cdoc->Create();
758  self::setSqlIndex($dbaccess, $docid);
759  }
760 
761  protected static function recreateFamilyView($dbaccess, $docname, $docid)
762  {
763  simpleQuery($dbaccess, sprintf("SELECT refreshFamilySchemaViews(%s, %s)", pg_escape_literal($docname) , pg_escape_literal(intval($docid))) , $res, true, true, true);
764  }
765 
766  protected static function getTableColumns($dbaccess, $schemaName, $tableName)
767  {
768  simpleQuery($dbaccess, sprintf("SELECT column_name FROM information_schema.columns WHERE table_schema = %s AND table_name = %s", pg_escape_literal($schemaName) , pg_escape_literal($tableName)) , $res, true, false, true);
769  return $res;
770  }
771 
772  protected static function alterTableAddColumn($dbaccess, $schemaName, $tableName, $columnName, $columnType)
773  {
774  simpleQuery($dbaccess, sprintf("ALTER TABLE %s.%s ADD COLUMN %s %s", pg_escape_identifier($schemaName) , pg_escape_identifier($tableName) , pg_escape_identifier($columnName) , $columnType) , $res, true, true, true);
775  }
776 
777  public static function createDocFile($dbaccess, $tdoc)
778  {
779  $GEN = getGen($dbaccess);
781  $dfile = "$pubdir/FDL$GEN/Class.Doc" . $tdoc["id"] . ".php";
782 
783  $err = self::__phpLintWriteFile($dfile, self::generateFamilyPhpClass($dbaccess, $tdoc));
784  if ($err != '') {
785  throw new \Dcp\Exception(sprintf("Error generating file '%s': %s", $dfile, $err));
786  }
787 
788  $attrfile = "$pubdir/FDL$GEN/Class.Attrid" . $tdoc["id"] . ".php";
789 
790  $err = self::__phpLintWriteFile($attrfile, self::AttrIdtoPhp($dbaccess, $tdoc));
791  if ($err != '') {
792  throw new \Dcp\Exception(sprintf("Error generating file '%s': %s", $attrfile, $err));
793  }
794 
795  return $dfile;
796  }
797 
798  public static function activateTrigger($dbaccess, $docid)
799  {
800  $cdoc = createTmpDoc($dbaccess, $docid, false);
801  $cdoc->exec_query($cdoc->sqltrigger(false, true) , 1);
802  $sqlcmds = explode(";", $cdoc->SqlTrigger());
803  //$cdoc = new_Doc($dbacceanss, $docid);
804  // print $cdoc->SqlTrigger();
805  foreach ($sqlcmds as $k => $sqlquery) {
806  if ($sqlquery != "") {
807  $cdoc->exec_query($sqlquery, 1);
808  }
809  }
810  }
811 
812  public static function setSqlIndex($dbaccess, $docid)
813  {
814  $cdoc = createTmpDoc($dbaccess, $docid, false);
815  $indexes = $cdoc->GetSqlIndex();
816  $msg = '';
817  if ($indexes) {
818  foreach ($indexes as $sqlIndex) {
819  $msg.= $cdoc->exec_query($sqlIndex);
820  }
821  }
822  return $msg;
823  }
824  /**
825  * refresh PHP Class & Postgres Table Definition
826  *
827  * @param string $dbaccess
828  * @param int $docid
829  *
830  * @return string error message
831  */
832  public static function refreshPhpPgDoc($dbaccess, $docid)
833  {
834  $err = '';
835  $query = new \QueryDb($dbaccess, "DocFam");
836  $query->AddQuery("doctype='C'");
837  $query->AddQuery("id=$docid");
838  $table1 = $query->Query(0, 0, "TABLE");
839  if ($query->nb > 0) {
840  $v = $table1[0];
841  $err = self::buildFamilyFilesAndTables($dbaccess, $v, false);
842  }
843 
844  return $err;
845  }
846 
847  public static function buildFamilyFilesAndTables($dbaccess, $familyData, $interactive = false)
848  {
850  $locked = false;
851  $savepointed = false;
852  try {
853  if (($err = $doc->setMasterLock(true)) !== '') {
854  throw new \Dcp\Core\Exception($err);
855  }
856  $locked = true;
857  if (($err = $doc->savePoint(__METHOD__)) !== '') {
858  throw new \Dcp\Core\Exception($err);
859  }
860  $savepointed = true;
861 
862  $phpfile = self::createDocFile($dbaccess, $familyData);
863  if ($interactive) {
864  print "$phpfile [" . $familyData["title"] . "(" . $familyData["name"] . ")]\n";
865  }
866  $msg = self::pgUpdateFamily($dbaccess, $familyData["id"], $familyData["name"]);
867  if ($interactive) {
868  print $msg;
869  } else {
870  AddLogMsg($msg);
871  }
872  self::activateTrigger($dbaccess, $familyData["id"]);
873  self::resetSystemEnum($familyData["id"]);
874 
875  if (($err = $doc->commitPoint(__METHOD__)) !== '') {
876  throw new \Dcp\Core\Exception($err);
877  }
878  $savepointed = false;
879  if (($err = $doc->setMasterLock(false)) !== '') {
880  throw new \Dcp\Core\Exception($err);
881  }
882  }
883  catch(\Exception $e) {
884  if ($savepointed) {
885  $doc->rollbackPoint(__METHOD__);
886  }
887  if ($locked) {
888  $doc->setMasterLock(false);
889  }
890  return $e->getMessage();
891  }
892  return '';
893  }
894  /**
895  * reset and record system enum into docenum table
896  *
897  * @param int $famid
898  */
899  protected static function resetSystemEnum($famid)
900  {
901  $sql = sprintf("select * from docattr where docid=%d and type = 'enum' and (phpfile is null or phpfile='-') and options ~ 'system=yes'", $famid);
902  simpleQuery('', $sql, $results);
903  foreach ($results as $attr) {
904  $attrid = $attr["id"];
905  \importDocumentDescription::recordEnum($famid, $attrid, $attr["phpfunc"], true);
906  }
907  }
908  /**
909  * complete attribute properties from parent attribute
910  *
911  * @param string $dbaccess
912  * @param \DocAttr $ta
913  *
914  * @return mixed
915  * @throws Db\Exception
916  */
917  protected static function completeAttribute($dbaccess, $ta)
918  {
919  $ta->id = substr($ta->id, 1);
920  $fromid = getFamFromId($dbaccess, $ta->docid);
921  $tfromid[] = $fromid;
922  while ($fromid = getFamFromId($dbaccess, $fromid)) {
923  $tfromid[] = $fromid;
924  }
925  $tfromid[] = $ta->docid; // itself
926  $query = new \QueryDb($dbaccess, "DocAttr");
927  $query->AddQuery(GetSqlCond($tfromid, 'docid'));
928  $query->AddQuery("id='" . pg_escape_string($ta->id) . "'");
929  $query->order_by = "docid";
930  $tas = $query->Query(0, 0, "TABLE");
931 
932  if ($query->nb == 0) {
933  error_log("MODATTR error for " . $ta->id);
934  return $ta;
935  } else {
936  $tw = $ta;
937 
938  foreach ($tas as $ta1) {
939  if (preg_match("/(.*)relativeOrder=([A-Za-z0-9_:-]+)(.*)/", $ta->options, $attrReg)) {
940  if (preg_match("/(.*)relativeOrder=([A-Za-z0-9_:-]+)(.*)/", $ta1["options"], $parentReg)) {
941  // Special case to copy parent options when relativeOrder is used
942  if (($parentReg[1] || $parentReg[3]) && (!$attrReg[1] && !$attrReg[3])) {
943  // Copy on if no explicit option is set
944  $tw->options = sprintf("%srelativeOrder=%s%s", $parentReg[1], $attrReg[2], $parentReg[3]);
945  }
946  }
947  }
948 
949  foreach ($ta1 as $k => $v) {
950  if ($v && (!$ta->$k)) {
951  $tw->$k = $v;
952  }
953  if ($ta->$k == "-") {
954  $tw->$k = "";
955  } // suppress value
956 
957  }
958  }
959 
960  return $tw;
961  }
962  }
963  /**
964  * get parent attributes
965  *
966  * @param string $dbaccess
967  * @param string $fromid
968  *
969  * @return array
970  * @throws Db\Exception
971  */
972  protected static function getParentAttributes($dbaccess, $fromid)
973  {
974  if ($fromid > 0) {
975  $query = new \QueryDb($dbaccess, "DocAttr");
976  $query->AddQuery(sprintf("docid=%d", $fromid));
977 
978  $pa = $query->Query(0, 0, "TABLE");
979  if (!$pa) {
980  $pa = [];
981  }
982 
983  $nextfromid = getFamFromId($dbaccess, $fromid);
984  if ($nextfromid > 0) {
985  $pa = array_merge(self::getParentAttributes($dbaccess, $nextfromid) , $pa);
986  }
987  $paf = array();
988  foreach ($pa as $v) {
989  $paf[$v["id"]] = $v;
990  if (preg_match('/\bdoctitle=(?P<attrid>[A-Za-z0-9_-]+)\b/', $v["options"], $m)) {
991  $vtitle = $v;
992  if ($m['attrid'] == 'auto') {
993  $vtitle["id"] = $v["id"] . "_title";
994  } else {
995  $vtitle["id"] = strtolower($m['attrid']);
996  }
997  $vtitle["type"] = "text";
998  $vtitle["options"] = "";
999  $paf[$vtitle["id"]] = $vtitle;
1000  }
1001  }
1002 
1003  return $paf;
1004  }
1005  return array();
1006  }
1007  /**
1008  * Extract the main type and the format from a type string
1009  *
1010  * @param string $type e.g. 'array("empty")'
1011  *
1012  * @return array() struct e.g. array('type' => 'array', 'format' => '"empty"')
1013  */
1014  public static function parseType($type)
1015  {
1016  if (preg_match('/^\s*(?P<type>[a-z]+)(?P<format>\(.+\))?\s*$/i', $type, $m)) {
1017  /* Remove leading and trailing parenthesis from format */
1018  if (empty($m['format'])) {
1019  $m['format'] = '';
1020  }
1021  $m['format'] = substr($m['format'], 1, -1);
1022  return array(
1023  'type' => $m['type'],
1024  'format' => $m['format']
1025  );
1026  }
1027  return array(
1028  'type' => $type,
1029  'format' => ''
1030  );
1031  }
1032 
1033  protected static function getTypeMain($type)
1034  {
1035  $p = parseType($type);
1036  return $p['type'];
1037  }
1038 
1039  protected static function getTypeFormat($type)
1040  {
1041  $p = parseType($type);
1042  return $p['format'];
1043  }
1044  /**
1045  * Get the content of a METHOD file without the PHP opening/closing tags and
1046  * without the @begin-method-ignore/@end-method-ignore sections.
1047  *
1048  * @param $filename
1049  *
1050  * @return string
1051  */
1052  protected static function getMethodFileInnerContents($filename)
1053  {
1054  $contents = file_get_contents($filename);
1055  if ($contents === false) {
1056  return '';
1057  }
1058  $contents = preg_replace('%(?: //[^\n]*\@begin-method-ignore| /\*+[^/]*?\@begin-method-ignore)(.*?)(?: //[^\n]*\@end-method-ignore[^\n]*| /\*+[^/]*?\@end-method-ignore[^/]*?\*/)%xms', '', $contents);
1059  $contents = str_replace(array(
1060  "<?php\n",
1061  "<?php\r\n",
1062  "\n?>"
1063  ) , "", $contents);
1064  return (string)$contents;
1065  }
1066 }
static getTypeFormat($type)
$tdoc
global $action
global $pubdir
Definition: vault_init.php:18
Exception class use exceptionCode to identifiy correctly exception.
Definition: exceptions.php:19
$filename
static getTableColumns($dbaccess, $schemaName, $tableName)
static viewExists($dbaccess, $schemaName, $viewName)
if($famId) $s
static setSqlIndex($dbaccess, $docid)
const DEFAULT_PUBDIR
Definition: Lib.Prefix.php:28
static createFamilyTable($dbaccess, $docid)
static tableExists($dbaccess, $schemaName, $tableName)
static AttrIdToPhp($dbaccess, $tdoc)
AddLogMsg($msg, $cut=80)
Definition: Lib.Common.php:77
$docid
Definition: cleanFamily.php:13
static getParentAttributes($dbaccess, $fromid)
static recordEnum($famid, $attrid, $phpfunc, $reset=false)
static createDocFile($dbaccess, $tdoc)
static phpLintFile($fileName, &$output)
Definition: CheckClass.php:86
static __phpLintWriteFile($fileName, $content)
static recreateFamilyView($dbaccess, $docname, $docid)
static alterTableAddColumn($dbaccess, $schemaName, $tableName, $columnName, $columnType)
getFamIdFromName($dbaccess, $name)
print
Definition: checklist.php:49
static getTypeMain($type)
new_Doc($dbaccess, $id= '', $latest=false)
$dir
Definition: resizeimg.php:144
GetSqlCond($Table, $column, $integer=false)
getFamFromId($dbaccess, $id)
getNameFromId($dbaccess, $id)
static completeAttribute($dbaccess, $ta)
parseType($type)
Definition: Lib.Attr.php:29
static buildFamilyFilesAndTables($dbaccess, $familyData, $interactive=false)
static getMethodFileInnerContents($filename)
$dbaccess
Definition: checkVault.php:17
if(($docid!==0)&&(!is_numeric($docid))) $query
simpleQuery($dbaccess, $query, &$result=array(), $singlecolumn=false, $singleresult=false, $useStrict=null)
Definition: Lib.Common.php:484
createTmpDoc($dbaccess, $fromid, $defaultvalue=true)
static refreshPhpPgDoc($dbaccess, $docid)
if($file) if($subject==""&&$file) if($subject=="") $err
activateTrigger($dbaccess, $docid)
Definition: Lib.Attr.php:8
static resetSystemEnum($famid)
getGen($dbaccess)
Definition: Lib.Util.php:27
static activateTrigger($dbaccess, $docid)
← centre documentaire © anakeen