Offline Server  1.6
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.DomainSyncApi.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
5  * @package FDL
6 */
7 /**
8  * Return offline domains where current user is affected
9  *
10  * @author Anakeen
11  * @version $Id: $
12  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
13  * @package OFFLINE
14  */
15 /**
16  */
17 
18 include_once ("DATA/Class.Collection.php");
19 include_once ("OFFLINE/Class.ExceptionCode.php");
20 include_once ("FDL/Class.DocWaitManager.php");
21 
23 {
24  const abortTransaction = "abortTransaction";
25  const successTransaction = "successTransaction";
26  const partialTransaction = "partialTransaction";
27  const documentNotRecorded = "documentNotRecorded";
28  const newPrefix = "DLID-";
29  /**
30  * internal domain document
31  * @var _OFFLINEDOMAIN
32  */
33  private $domain = null;
34  /**
35  * parent object
36  * @var DomainApi
37  */
38  private $domainApi = null;
39  public function __construct(Dir & $domain = null, DomainApi & $domainApi = null)
40  {
41  $this->domain = $domain;
42  $this->domainApi = $domainApi;
43  }
44  private static function setError($err)
45  {
46  throw new Exception($err);
47  }
48  /**
49  * test if document must be returned to the client
50  *
51  * @param Doc $doc
52  * @param array $stillRecorded
53  * @return true is client document is uptodate
54  */
55  public static function isUpToDate(Doc & $doc, array & $stillRecorded)
56  {
57 
58  if (!$stillRecorded[$doc->initid]) return false;
59  if (intval($stillRecorded[$doc->initid]->locked) != intval($doc->locked)) return false;
60  if (intval($stillRecorded[$doc->initid]->lockdomainid) != intval($doc->lockdomainid)) return false;
61  if ($stillRecorded[$doc->initid]->revdate >= $doc->revdate) return true;
62  return false;
63  }
64  /**
65  * get share folder documents
66  * @return DocumentList
67  */
68  public function getSharedDocuments($config)
69  {
70  $err = $this->callHook("onBeforePullSharedDocuments");
71  if (!$err) {
72  $callback = null;
73  $stillRecorded = array();
74  if (is_array($config->stillRecorded)) {
75 
76  foreach ($config->stillRecorded as $record) {
77  $stillRecorded[$record->initid] = $record;
78  }
79  }
80 
81  if ($this->domain->hook()) {
82  $domain = $this->domain;
83  $callback = function (&$doc) use ($domain, $stillRecorded)
84  {
85  $isUpToDate = DomainSyncApi::isUpToDate($doc, $stillRecorded);
86  if ($isUpToDate) return false;
87  $err = call_user_func_array(array(
88  $domain->hook() ,
89  $method = "onPullDocument"
90  ) , array(&$domain, &$doc
91  ));
92 
93  return (empty($err) || ($err === true));
94  };
95  } else {
96  if (count($stillRecorded) > 0) {
97  $callback = function (&$doc) use ($stillRecorded)
98  {
99  $isUpToDate = DomainSyncApi::isUpToDate($doc, $stillRecorded);
100  if ($isUpToDate) return false;
101  return true;
102  };
103  }
104  }
105  $out = $this->domainApi->getSharedDocuments($config, $callback);
106  $out->documentsToDelete = $this->getIntersect($this->domain->getSharedFolder() , $stillRecorded);
107  } else {
108  $out=new stdClass();
109  $out->error = $err;
110  }
111  $log = '';
112  $log->error = $out->error;
113  $log->documentsToDelete = $out->documentsToDelete;
114  if (is_array($out->content)) {
115  foreach ($out->content as & $rdoc) {
116  $log->documentsToUpdate[] = $rdoc["properties"]["initid"];
117  }
118  }
119  $this->domain->addLog(__METHOD__, $log);
120  return $out;
121  }
122 
123  private function getIntersect(Dir & $folder, array & $stillRecorded)
124  {
125  $serverInitids = $folder->getContentInitid();
126  $clientInitids = array_keys($stillRecorded);
127  return array_values(array_diff($clientInitids, $serverInitids));
128  }
129  /**
130  * revert document into user space
131  * @return Fdl_Document
132  */
133  public function revertDocument($config)
134  {
135  $docid = $config->docid;
136  $doc = new_doc(getDbaccess() , $docid, true);
137 
138  $out=new stdClass();
139  if ($doc->isAlive()) {
140  $err = $this->callHook("onPullDocument", $doc);
141  if ($err == "" || $err === true) {
142  $this->domain->addFollowingStates($doc);
143 
144  $out = $this->domainApi->revertDocument($config);
145  } else {
146  $out->error = $err;
147  }
148  } else {
149  $out->error = sprintf(_("document %s not found") , $docid);
150  }
151  $log = "";
152  $log->initid = $doc->initid;
153  $log->title = $doc->getTitle();
154  $log->error = $out->error;
155  $this->domain->addLog(__METHOD__, $log);
156  return $out;
157  }
158  /**
159  * unlink document from user space
160  * @return Fdl_Document
161  */
162  public function removeUserDocument($config)
163  {
164  $docid = $config->docid;
165  $doc = new_doc(getDbaccess() , $docid, true);
166 
167  $out=new stdClass();
168  if ($doc->isAlive()) {
169  $out = $this->domainApi->removeUserDocument($config);
170 
171  } else {
172  $out->error = sprintf(_("document %s not found") , $docid);
173  }
174  $log = "";
175  $log->initid = $doc->initid;
176  $log->title = $doc->getTitle();
177  $log->error = $out->error;
178  $this->domain->addLog(__METHOD__, $log);
179  return $out;
180  }
181  /**
182  * book document into user space
183  * @return Fdl_Document
184  */
185  public function bookDocument($config)
186  {
187  $docid = $config->docid;
188  $doc = new_doc(getDbaccess() , $docid, true);
189  $out=new stdClass();
190  if ($doc->isAlive()) {
191  $this->domain->addFollowingStates($doc);
192 
193  $out = $this->domainApi->bookDocument($config);
194 
195  } else {
196  $out->error = sprintf(_("document %s not found") , $docid);
197  }
198  $log = "";
199  $log->initid = $doc->initid;
200  $log->title = $doc->getTitle();
201  $log->error = $out->error;
202  $this->domain->addLog(__METHOD__, $log);
203  return $out;
204  }
205  /**
206  * unbook document from user space
207  * @return Fdl_Document
208  */
209  public function unbookDocument($config)
210  {
211  $docid = $config->docid;
212  $doc = new_doc(getDbaccess() , $docid, true);
213  $out=new stdClass();
214  if ($doc->isAlive()) {
215 
216  $this->domain->addFollowingStates($doc);
217 
218  $out = $this->domainApi->unbookDocument($config);
219 
220  } else {
221  $out->error = sprintf(_("document %s not found") , $docid);
222  }
223  $log = "";
224  $log->initid = $doc->initid;
225  $log->title = $doc->getTitle();
226  $log->error = $out->error;
227  $this->domain->addLog(__METHOD__, $log);
228  return $out;
229  }
230  /**
231  * get user folder documents
232  * @return DocumentList
233  */
234  public function getUserDocuments($config)
235  {
236  $err = $this->callHook("onBeforePullUserDocuments");
237  if (!$err) {
238  $callback = null;
239  $stillRecorded = array();
240  if (is_array($config->stillRecorded)) {
241  foreach ($config->stillRecorded as $record) {
242  $stillRecorded[$record->initid] = $record;
243  }
244  }
245  if ($this->domain->hook()) {
246  $domain = $this->domain;
247  $callback = function (&$doc) use ($domain, $stillRecorded)
248  {
249  $isUpToDate = DomainSyncApi::isUpToDate($doc, $stillRecorded);
250  if ($isUpToDate) return false;
251  $domain->addFollowingStates($doc);
252  $err = call_user_func_array(array(
253  $domain->hook() ,
254  $method = "onPullDocument"
255  ) , array(&$domain, &$doc
256  ));
257  return (empty($err) || ($err === true));
258  };
259  } else {
260  $domain = $this->domain;
261  $callback = function (&$doc) use ($domain, $stillRecorded)
262  {
263  $isUpToDate = DomainSyncApi::isUpToDate($doc, $stillRecorded);
264  if ($isUpToDate) return false;
265  $domain->addFollowingStates($doc);
266  return true;
267  };
268  }
269  $out = $this->domainApi->getUserDocuments($config, $callback);
270  $out->documentsToDelete = $this->getIntersect($this->domain->getUserFolder() , $stillRecorded);
271  } else {
272  $out=new stdClass();
273  $out->error = $err;
274  }
275  $log = '';
276  $log->error = $out->error;
277  $log->documentsToDelete = $out->documentsToDelete;
278  if (is_array($out->content)) {
279  foreach ($out->content as & $rdoc) {
280  $log->documentsToUpdate[] = $rdoc["properties"]["initid"];
281  }
282  }
283  $this->domain->addLog(__METHOD__, $log);
284  return $out;
285  }
286  /**
287  * get Acknowledgement after user folder documents
288  * @return string
289  */
290  public function getUserDocumentsAcknowledgement($config)
291  {
292  $out = '';
293  $out->acknowledgement = $this->callHook("onAfterPullUserDocuments");
294  return $out;
295  }
296  /**
297  * get Acknowledgement after user folder documents
298  * @return string
299  */
300  public function getSharedDocumentsAcknowledgement($config)
301  {
302  $out = '';
303  $out->acknowledgement = $this->callHook("onAfterPullSharedDocuments");
304  return $out;
305  }
306  /**
307  * set file to document
308  * @return D document List
309  */
310  public function pushFile($config)
311  {
312  //print_r($config);
313  $docid = $config->docid;
314  $aid = $config->aid;
315  $index = - 1;
316  if (preg_match('/(.*)\[([0-9]+)\]$/', $aid, $reg)) {
317  $index = $reg[2];
318  $aid = trim($reg[1]);
319  }
320  $path = 'php://input';
321  $out = '';
322  $tmpfile = tempnam(getTmpDir() , 'pushFile');
323  if ($tmpfile == false) {
324  $err = sprintf("cannot create temporay file %s", $tmpfile);
325  } else {
326  copy($path, $tmpfile);
327  $filename = $config->filename;
328 
329  if ($this->isLocalIdenticator($docid)) {
330  $localid = $docid;
331  $docid = $this->numerizeId($docid);
332  }
333  $wdoc = DocWaitManager::getWaitingDoc($docid);
334  //$doc = new_doc(getDbAccess(), $docid);
335  if ($wdoc) {
336  $doc = $wdoc->getWaitingDocument();
337  // print $doc->getTitle();
338  $oa = $doc->getAttribute($aid);
339  // print_r($oa);
340  if ($oa) {
341  if (!$doc->id) {
342  // it is a new doc
343  $doc->id = 0;
344  $doc->initid = $docid;
345  $doc->localid = $localid;
346  }
347  $err = $doc->storeFile($oa->id, $tmpfile, $filename, $index);
348  @unlink($tmpfile);
349  $err = DocWaitManager::saveWaitingDoc($doc, $this->domain->id, $config->transaction);
350  }
351  // $err = DocWaitManager::saveWaitingDoc($doc);
352 
353  }
354  }
355  $this->domain->addLog(__METHOD__, $out);
356  $out->error = $err;
357  return $out;
358  }
359  /**
360  *
361  * Enter description here ...
362  * @param unknown_type $rawdoc
363  *
364  */
365  private function raw2doc($rawdoc, &$doc)
366  {
367  $fromid = $rawdoc->properties->fromid;
368  $doc = createDoc(getDbAccess() , $fromid, false, false, false); // no default values
369  $err = '';
370  if (!$doc) {
371  $err = sprintf("cannot create document %s", $fromid);
372  } else {
373  $props = array();
374  if ($this->isNewDocument($rawdoc)) {
375  $rawdoc->properties->localid = $rawdoc->properties->id;
376  $rawdoc->properties->initid = $this->numerizeId($rawdoc->properties->id);
377  $rawdoc->properties->id = 0;
378  }
379  foreach ($rawdoc->properties as $k => $v) {
380  if (is_array($v)) $v = implode("\n", $v);
381  $props[$k] = $v;
382  }
383  $doc->affect($props);
384  foreach ($rawdoc->values as $k => $v) {
385 
386  $oa = $doc->getAttribute($k);
387  if ($oa) {
388  if ($oa->type == "docid") {
389  $v = $this->numerizeAllId($v);
390  }
391  if ($v == '') $v = " ";
392  $serr = $doc->setValue($k, $v);
393  if ($serr) {
394  $err.= sprintf("%s : %s", $oa->getLabel() , $serr);
395  }
396  }
397  }
398  $doc->locked = - 1; // to not be updated
399 
400  }
401  return $err;
402  }
403 
404  private function isNewDocument($rawdoc)
405  {
406  return $this->isLocalIdenticator($rawdoc->properties->id);
407  }
408  private function isLocalIdenticator($id)
409  {
410  if (preg_match('/^' . $this::newPrefix . '/', $id)) return true;
411  return false;
412  }
413  /**
414  * Modify waiting doc
415  * @return Fdl_Document document
416  */
417  public function pushDocument($config)
418  {
419  $rawdoc = $config->document;
420 
421  if ($rawdoc) {
422  $out = '';
423  $doc = null;
424 
425  $extraData = $rawdoc->properties->pushextradata;
426  if ($extraData === null) {
427  $extraData=''; // to update it
428  }
429 
430  if (!$this->isNewDocument($rawdoc)) {
431  $refdoc = new_doc(getDbAccess() , $rawdoc->properties->id, true);
432  $err = $this->verifyPrivilege($refdoc);
433  }
434  if ($err == "") {
435 
436  $err = $this->raw2doc($rawdoc, $doc);
437  }
438 
439  if ($err == "") {
440  $err = $this->callHook("onBeforePushDocument", $doc, $extraData);
441 
442  if (!$err) {
443 
444  $err = DocWaitManager::saveWaitingDoc($doc, $this->domain->id, $config->transaction, $extraData);
445  }
446  if ($err) {
447  $out->error = $err;
448  } else {
449  $message = $this->callHook("onAfterPushDocument", $doc, $extraData);
450  $fdoc = new Fdl_Document($doc->id, null, $doc);
451  $out = $fdoc->getDocument(true, false);
452  $out["message"] = $message;
453  }
454  } else {
455  $waitDoc = DocWaitManager::getWaitingDoc($rawdoc->properties->initid);
456  if (!$waitDoc) {
457  $doc = new_doc(getDbAccess() , $rawdoc->properties->id, true);
458  $err = DocWaitManager::saveWaitingDoc($doc, $this->domain->id, $config->transaction, $extraData);
459  } else {
460  $waitDoc->transaction = $config->transaction;
461  $waitDoc->status = $waitDoc::invalid;
462  $waitDoc->statusmessage = $err;
463  $waitDoc->modify();
464  }
465  $out->error = sprintf(_("push:invalid document : %s") , $err);
466  }
467  } else {
468  $out=new stdClass();
469  $out->error = _("push:no document found");
470  }
471  if (!$waitDoc) {
472  $waitDoc = DocWaitManager::getWaitingDoc($rawdoc->properties->initid);
473  }
474  if ($waitDoc) {
475  $log = (object)$waitDoc->getValues();
476  unset($log->orivalues);
477  unset($log->values);
478  } else {
479  $log = '';
480  }
481  $log->error = $out->error;
482  if (is_array($out)) {
483  $log->message = $out["message"];
484  }
485  $this->domain->addLog(__METHOD__, $log);
486  return $out;
487  }
488  private function callHook($method, &$arg1 = null, &$arg2 = null, &$arg3 = null)
489  {
490 
491  if ($this->domain->hook()) {
492  if (method_exists($this->domain->hook() , $method)) {
493  return call_user_func_array(array(
494  $this->domain->hook() ,
495  $method
496  ) , array(&$this->domain, &$arg1, &$arg2, &$arg3
497  ));
498  }
499  }
500  return null;
501  }
502  /**
503  * reset all waitings Transaction
504  * @return object transactionId
505  */
506  public function resetWaitingDocs()
507  {
508  include_once ("FDL/Class.DocWaitManager.php");
509 
510  $err = DocWaitManager::clearWaitingDocs($this->domain->id, $this->domain->getSystemUserId());
511 
512  $out = '';
513  $out->error = $err;
514 
515  return $out;
516  }
517  /**
518  * update report file
519  * store file user folder
520  * @return string content of the file
521  */
522  public function getReport($config)
523  {
524  $report = '';
525  $err = $this->domain->updateReport($this->domain->getSystemUserId() , $report);
526  $out = '';
527  if (!$err) $out->report = $report;
528  $out->error = $err;
529 
530  return $out;
531  }
532  /**
533  * Begin Transaction
534  * @return object transactionId
535  */
536  public function beginTransaction()
537  {
538  $err = $this->callHook("onBeforePushTransaction");
539  $out = '';
540  $out->error = $err;
541  if (!$err) {
542  $out->transactionId = DocWaitManager::getTransaction();
543  }
544  $this->domain->addLog(__METHOD__, $out);
545  return $out;
546  }
547  /**
548  * Verify all document in list to computeStatus
549  * @param DbObjectList $waitings
550  * @param stdClass $out
551  */
552  private function verifyAllConflict(DbObjectList & $waitings, &$out)
553  {
554  $err = '';
555  foreach ($waitings as $k => $waitDoc) {
556  $status = $waitDoc->computeStatus();
557  $out->detailStatus[$waitDoc->refererinitid] = array(
558  "statusMessage" => $waitDoc->statusmessage ? $waitDoc->statusmessage : _("verified") ,
559  "statusCode" => $waitDoc->status
560  );
561  if (!$waitDoc->isValid()) {
562  $err = $waitDoc->statusmessage;
563  }
564  }
565  return $err;
566  }
567 
568  public function verifyPrivilege(Doc & $doc)
569  {
570  if (!$this->domain->isMember()) return _("not a member domain");
571  $err = $doc->canEdit(false);
572 
573  if (!$err) {
574  // verify domain lock
575  if ($doc->lockdomainid != $this->domain->id) $err = sprintf(_("lock must be in domain %s") , $this->domain->getTitle());
576  }
577 
578  return $err;
579  }
580  /*
581  function numerizeLocalLinks(Doc &$doc)
582  {
583  $oas = $doc->getNormalAttributes();
584  foreach ( $oas as $aid => $oa ) {
585  if ($oa->type == "docid") {
586  $value = $doc->getValue($aid);
587  if ($value) {
588  $doc->setValue($aid, preg_replace("/(DLID-[a-f0-9-]+)/se", "\$this->numerizeId('\\1')", $value));
589  }
590  }
591 
592  }
593  }*/
594 
595  private function numerizeAllId($s)
596  {
597  return preg_replace("/(DLID-[a-f0-9-]+)/se", "\$this->numerizeId('\\1')", $s);
598  }
599  /**
600  * localid to numeric id
601  * @param string $s DLID-<uuid>
602  * @return int
603  */
604  private function numerizeId($s)
605  {
606  $u = crc32($s);
607  if ($u < 0) return $u;
608  $u = abs($u);
609  if (($u >> 31) == 0) return -($u);
610  return -round($u / 2);
611  }
612  /**
613  * change local relation link by server document identificator
614  * @param stdClass $results
615  */
616  private function updateLocalLink(&$results)
617  {
618  $details = $results->detailStatus;
619  $localIds = array();
620  $serverIds = array();
621  foreach ($details as $k => $v) {
622  $lid = $v['localId'];
623  if ($lid) {
624  $localIds[] = $this->numerizeId($lid);
625  $serverIds[] = $k;
626  }
627  }
628 
629  $list = new DocumentList();
630  $list->addDocumentIdentificators($serverIds);
631  foreach ($list as $id => $doc) {
632  $oas = $doc->getNormalAttributes();
633  $needModify = false;
634  foreach ($oas as $aid => $oa) {
635  if ($oa->type == "docid") {
636  $value = $doc->getValue($aid);
637  if ($value) {
638  $nvalue = str_replace($localIds, $serverIds, $value);
639  if ($nvalue != $value) {
640  $doc->setValue($aid, $nvalue);
641  $needModify = true;
642  }
643  }
644  }
645  }
646  if ($needModify) $doc->modify();
647  }
648  }
649  /**
650  * End transaction
651  * @return object
652  */
653  public function endTransaction($config)
654  {
655  if ($config->transaction) {
656  $out = '';
657  $err = '';
658  $waitings = DocWaitManager::getWaitingDocs($config->transaction);
659 
660  $policy = $this->domain->getValue('off_transactionpolicy');
661  if ($policy == "global") {
662  // need verify global conflict
663  $status = $this->verifyAllConflict($waitings, $out);
664  $err = $status;
665  }
666  if (!$err) {
667  $err = $this->callHook("onAfterPushTransaction");
668  }
669  if (!$err) {
670 
671  $out->detailStatus = array();
672  $beforeSavePoint = "synchro" . $config->transaction;
673  if ($policy == "global") {
674  $this->domain->savePoint($beforeSavePoint);
675  }
676  // main save is here
677  $out->detailStatus = $this->saveWaitings($waitings);
678  // analyze results
679  $completeSuccess = true;
680  $allFailure = true;
681  foreach ($out->detailStatus as $aStatus) {
682 
683  if ($aStatus['isValid']) {
684  $allFailure = false;
685  } else {
686  $completeSuccess = false;
687  }
688  }
689  $message = '';
690  if ($allFailure) {
691  if (count($out->detailStatus) > 0) {
692  $out->status = self::abortTransaction;
693  } else {
694  // nothing has be done / no work is a good work
695  $out->status = self::successTransaction;
696  }
697  } else {
698  $out->status = $completeSuccess ? self::successTransaction : self::partialTransaction;
699  if ($completeSuccess || ($policy != "global")) {
700  $this->updateLocalLink($out);
701  $message = $this->callHook("onAfterSaveTransaction");
702  }
703  }
704 
705  if ($policy == "global") {
706  if ($out->status == self::successTransaction) {
707  $this->domain->commitPoint($beforeSavePoint);
708  } else {
709  $out->status = self::abortTransaction; // no partial in global mode
710  $this->domain->rollbackPoint($beforeSavePoint);
711  }
712  }
713  $out->message = $message;
714  $out->error = $err;
715  } else {
716  $out->status = self::abortTransaction;
717  $out->statusMessage = $err;
718  }
719  } else {
720  $out=new stdClass();
721  $out->error = _("endTransaction:no transaction identificator");
722  $out->status = self::abortTransaction;
723  }
724  $this->domain->addLog(__METHOD__, $out);
725  $ufolder = $this->domain->getUserFolder();
726  $out->manageWaitingUrl = getParam("CORE_EXTERNURL") . '?app=OFFLINE&action=OFF_ORGANIZER&domain=0&dirid=' . $ufolder->id . '&transaction=' . $config->transaction;
727  return $out;
728  }
729 
730  private function saveWaitings(&$waitings)
731  {
732  $out = array();
733  foreach ($waitings as $k => $waitDoc) {
734  if ($waitDoc->status == $waitDoc::invalid) {
735  $out[$waitDoc->refererinitid] = array(
736  "statusMessage" => $waitDoc->statusmessage,
737  "statusCode" => $waitDoc->status,
738  "isValid" => false
739  );
740  } else {
741  $waitPoint = "docw" . $k;
742  $this->domain->savePoint($waitPoint);
743  $needToRollback = false;
744 
745  $eExtra = $waitDoc->getExtraData();
746  $saveerr = $this->callHook("onBeforeSaveDocument", $waitDoc->getWaitingDocument() , $waitDoc->getRefererDocument() , $eExtra);
747  $savectxerr = '';
748  if (!$saveerr) {
749  if ($waitDoc->getRefererDocument()) {
750  $saveerr = $this->verifyPrivilege($waitDoc->getRefererDocument());
751  $savectxerr = "getRefererDocument";
752  }
753  } else {
754  $savectxerr = "onBeforeSaveDocument";
755  }
756  if ($saveerr == "") {
757  $saveInfo = null;
758  $saveerr = $waitDoc->save($saveInfo);
759  $out[$waitDoc->refererinitid] = array(
760  "statusMessage" => $waitDoc->statusmessage,
761  "saveInfo" => $saveInfo,
762  "statusCode" => $waitDoc->status,
763  "localId" => $waitDoc->localid,
764  "isValid" => $waitDoc->isValid()
765  );
766  if ($saveerr == '') {
767  if ($waitDoc->localid) {
768  $this->domain->insertUserDocument($waitDoc->refererinitid, $this->domain->getSystemUserId() , true);
769  $morelinks = $this->resolveLocalLinks($waitDoc->localid, $waitDoc->refererinitid);
770  foreach ($morelinks as $mid => $link) {
771  if (!$out[$mid]) $out[$mid] = $link;
772  }
773  }
774  $message = $this->callHook("onAfterSaveDocument", $waitDoc->getRefererDocument() , $eExtra);
775  $out[$waitDoc->refererinitid]["saveInfo"]->onAfterSaveDocument = $message;
776  if ($eExtra->changeState) {
777  $refererDocument = $waitDoc->getRefererDocument();
778  $beforeChangeStateReferId = $refererDocument->getProperty("id");
779  $message = $this->afterSaveChangeState($refererDocument, $eExtra->changeState);
780  if ($message && $beforeChangeStateReferId === $refererDocument->getProperty("id")) {
781  $needToRollback = true;
782  }
783  $out[$waitDoc->refererinitid]["saveInfo"]->onAfterSaveChangeState = $message;
784  }
785  } else {
786  $needToRollback = true;
787  }
788  } else {
789  $needToRollback = true;
790  }
791  if (!$needToRollback) {
792  $waitDoc->getRefererDocument()->addComment("synchronised");
793  $this->domain->commitPoint($waitPoint);
794  } else {
795  $failOut = array(
796  "statusMessage" => $saveerr,
797  "statusContext" => $savectxerr,
798  "statusCode" => self::documentNotRecorded,
799  "isValid" => false
800  );
801  if (is_array($out[$waitDoc->refererinitid])) {
802  $out[$waitDoc->refererinitid] = array_merge($out[$waitDoc->refererinitid], $failOut);
803  } else {
804  $out[$waitDoc->refererinitid] = $failOut;
805  }
806  $this->domain->rollbackPoint($waitPoint);
807  // need to redo modify cause rollback
808  $waitDoc->status = $out[$waitDoc->refererinitid]["statusCode"];
809  $waitDoc->statusmessage = $out[$waitDoc->refererinitid]["statusMessage"];
810  $waitDoc->modify(true, array("status", "statusmessage"));
811  $waitDoc->getRefererDocument()->addComment(sprintf(_("synchro: %s") , $waitDoc->statusmessage) , HISTO_ERROR);
812  }
813  }
814  }
815 
816  return $out;
817  }
818 
819  private function resolveLocalLinks($localId, $serverId)
820  {
821  $numLocalId = $this->numerizeId($localId);
822  $waitings = DocWaitManager::getWaitingDocsByDomain($this->domain->id);
823  $out = array();
824  foreach ($waitings as $k => $waitDoc) {
825  if ($waitDoc->status == $waitDoc::upToDate) {
826 
827  $doc = $waitDoc->getRefererDocument();
828  if ($doc) {
829  $oas = $doc->getNormalAttributes();
830  $needModify = false;
831  foreach ($oas as $aid => $oa) {
832  if ($oa->type == "docid") {
833  $value = $doc->getValue($aid);
834  if ($value) {
835  $nvalue = str_replace($numLocalId, $serverId, $value);
836  if ($nvalue != $value) {
837  $doc->setValue($aid, $nvalue);
838  $needModify = true;
839  }
840  }
841  }
842  }
843  if ($needModify) {
844  $doc->modify();
845 
846  $out[$waitDoc->refererinitid] = array(
847  "statusMessage" => $waitDoc->statusmessage,
848  "statusCode" => $waitDoc->status,
849  "isValid" => true
850  );
851  }
852  }
853  }
854  }
855 
856  return $out;
857  }
858 
859  private function afterSaveChangeState(Doc & $doc, $newState)
860  {
861 
862  $err = $doc->setState($newState, sprintf(_("synchronize change state to %s"), $newState));
863  if ($doc->canEdit(false) === '' && $doc->isInDomain()) {
864  $err .= $doc->lockToDomain($this->domain->getProperty("id"), DOC::getSystemUserId());
865  }
866  return $err;
867  }
868 }
869 
871 {
872  /**
873  * @var int document id
874  */
875  public $id;
876  /**
877  * @var string document title
878  */
879  public $title;
880  /**
881  * @var string status of document (reserved, inserted or error)
882  */
883  public $status;
884  /**
885  * @var string error message
886  */
888  /**
889  * @var string status error message (return of canEdit())
890  */
892 
894  {
895  $this->id = $id;
896  $this->title = $title;
897  $this->status = $status;
898  $this->errorMessage = $errorMessage;
899  $this->statusErrorMessage = $statusErrorMessage;
900  }
901 }
__construct($id, $title, $status, $errorMessage, $statusErrorMessage)
__construct(Dir &$domain=null, DomainApi &$domainApi=null)
verifyPrivilege(Doc &$doc)
static isUpToDate(Doc &$doc, array &$stillRecorded)
getSharedDocumentsAcknowledgement($config)
getSharedDocuments($config)
getUserDocumentsAcknowledgement($config)
← centre documentaire © anakeen - published under CC License - Dynacase