1<?php
2
3namespace dokuwiki\plugin\farmsync\meta;
4
5
6class PageUpdates extends EntityUpdates {
7
8    public function updateEntity($page, $source, $target) {
9        $result = new UpdateResults($page, $target);
10        $sourceModTime = $this->farm_util->getRemoteFilemtime($source, $page);
11        $sourceText = $this->farm_util->readRemotePage($source, $page);
12
13        if (!$this->farm_util->remotePageExists($target, $page)) {
14            $this->farm_util->saveRemotePage($target, $page, $sourceText, $sourceModTime);
15            $result->setMergeResult('new file');
16            $this->results[$target]['passed'][] = $result;
17            return;
18        }
19        $targetModTime = $this->farm_util->getRemoteFilemtime($target, $page);
20        $targetText = $this->farm_util->readRemotePage($target, $page);
21        if ($targetModTime == $sourceModTime && $targetText == $sourceText) {
22            $result->setMergeResult('unchanged');
23            $this->results[$target]['passed'][] = $result;
24            return;
25        }
26
27        $sourceArchiveText = $this->farm_util->readRemotePage($source, $page, null, $targetModTime);
28        if ($targetModTime < $sourceModTime && $sourceArchiveText == $targetText) {
29            $this->farm_util->saveRemotePage($target, $page, $sourceText, $sourceModTime);
30            $result->setMergeResult('file overwritten');
31            $this->results[$target]['passed'][] = $result;
32            return;
33        }
34
35        // We have to merge
36        $commonroot = $this->farm_util->findCommonAncestor($page, $source, $target);
37        $diff3 = new \Diff3(explode("\n", $commonroot), explode("\n", $targetText), explode("\n", $sourceText));
38
39        // prepare labels
40        $label1 = '✎————————————————— ' . $this->getLang('merge_animal') . ' ————';
41        $label3 = '✏————————————————— ' . $this->getLang('merge_source') . ' ————';
42        $label2 = '✐————————————————————————————————————';
43        $final = join("\n", $diff3->mergedOutput($label1, $label2, $label3));
44        if ($final == $targetText) {
45            $result->setMergeResult('unchanged');
46            $this->results[$target]['passed'][] = $result;
47            return;
48        }
49        if (!$diff3->_conflictingBlocks) {
50            $this->farm_util->saveRemotePage($target, $page, $final);
51            $result->setFinalText($final);
52            $result->setMergeResult('merged without conflicts');
53            $this->results[$target]['passed'][] = $result;
54            return;
55        }
56        $result = new PageConflict($page, $target);
57        $result->setMergeResult('merged with conflicts');
58        $result->setConflictingBlocks($diff3->_conflictingBlocks);
59        $result->setFinalText($final);
60        $this->results[$target]['failed'][] = $result;
61        return;
62    }
63
64    protected function preProcessEntities($pagelines) {
65        $pages = array();
66        foreach ($pagelines as $line) {
67            $pages = array_merge($pages, $this->getDocumentsFromLine($this->source, $line));
68        }
69        array_unique($pages);
70        return $pages;
71    }
72
73
74    function printProgressLine($target, $i, $total) {
75        echo sprintf($this->getLang('progress:pages'), $target, $i, $total) . "</br>";
76    }
77
78    protected function printResultHeading() {
79        echo "<h3>".$this->getLang('heading:pages')."</h3>";
80    }
81
82    /**
83     * @param string $source
84     * @param string $line
85     *
86     * @return \string[]
87     *
88     */
89    public function getDocumentsFromLine($source, $line) {
90        if (trim($line) == '') return array();
91        $cleanline = str_replace('/', ':', $line);
92        $namespace = join(':', explode(':', $cleanline, -1));
93        $documentdir = dirname($this->farm_util->getRemoteFilename($source, $cleanline, null, false));
94        $search_algo = 'search_allpages';
95        $documents = array();
96
97        if (substr($cleanline, -3) == ':**') {
98            $nsfiles = array();
99            search($nsfiles, $documentdir, $search_algo, array());
100            $documents = array_map(function ($elem) use ($namespace) {
101                return $namespace . ':' . $elem['id'];
102            }, $nsfiles);
103        } elseif (substr($cleanline, -2) == ':*') {
104            $nsfiles = array();
105            search($nsfiles, $documentdir, $search_algo, array('depth' => 1));
106            $documents = array_map(function ($elem) use ($namespace) {
107                return $namespace . ':' . $elem['id'];
108            }, $nsfiles);
109        } else {
110            $document = $cleanline;
111            if (substr(noNS($document), 0, 1) == '_') return array();
112            if (in_array(substr($document, -1), array(':', ';'))) {
113                $document = $this->handleStartpage($source, $document);
114            }
115            if (!$this->farm_util->remotePageExists($source, $document)) {
116                msg("Page $document does not exist in source wiki!", -1);
117                return array();
118            }
119            $documents[] = cleanID($document);
120        }
121
122        return $documents;
123    }
124}
125