1<?php
2
3namespace dokuwiki\plugin\farmsync\meta;
4
5
6class TemplateUpdates extends EntityUpdates {
7
8    public function updateEntity($template, $source, $target) {
9        $sourceModTime = $this->farm_util->getRemoteFilemtime($source, $template, false, false);
10        $result = new UpdateResults($template, $target);
11
12        $targetFN = $this->farm_util->getRemoteFilename($target, $template, null, false);
13        $sourceContent = $this->farm_util->readRemotePage($source, $template, false);
14
15        if (!$this->farm_util->remotePageExists($target, $template, false)) {
16            $this->farm_util->replaceRemoteFile($targetFN, $sourceContent, $sourceModTime);
17            $result->setMergeResult('new file');
18            $this->results[$target]['passed'][] = $result;
19            return;
20        }
21        $targetModTime = $this->farm_util->getRemoteFilemtime($target, $template, false, false);
22        if ($sourceContent == $this->farm_util->readRemotePage($target, $template, false)) {
23            $result->setMergeResult('unchanged');
24            $this->results[$target]['passed'][] = $result;
25            return;
26        }
27        if ($targetModTime < $sourceModTime) {
28            $this->farm_util->replaceRemoteFile($targetFN, $sourceContent, $sourceModTime);
29            $result->setMergeResult('file overwritten');
30            $this->results[$target]['passed'][] = $result;
31            return;
32        }
33        $result = new TemplateConflict($template, $target);
34        $result->setMergeResult('merged with conflicts');
35        $this->results[$target]['failed'][] = $result;
36    }
37
38    protected function preProcessEntities($pagelines) {
39        $templates = array();
40        foreach ($pagelines as $line) {
41            $templates = array_merge($templates, $this->getDocumentsFromLine($this->source, $line));
42        }
43        array_unique($templates);
44        return $templates;
45    }
46
47
48    function printProgressLine($target, $i, $total) {
49        echo sprintf($this->getLang('progress:templates'), $target, $i, $total) . "</br>";
50    }
51
52
53    /**
54     * This function is in large parts a copy of the core function search().
55     * However, as opposed to core- search(), this function will also return templates,
56     * i.e. files starting with an underscore character.
57     *
58     * $opts['depth']   recursion level, 0 for all
59     *
60     * @param   string $base Where to start the search.
61     * @param   string $dir Current directory beyond $base
62     * @param             $lvl
63     * @param             $opts
64     *
65     * @return array|bool
66     */
67    public function getTemplates($base, $dir = '', $lvl = 0, $opts = array()) {
68        $dirs = array();
69        $files = array();
70        $items = array();
71
72        // safeguard against runaways #1452
73        if ($base == '' || $base == '/') {
74            throw new RuntimeException('No valid $base passed to search() - possible misconfiguration or bug');
75        }
76
77        //read in directories and files
78        $dh = @opendir($base . '/' . $dir);
79        if (!$dh) {
80            return array();
81        }
82        while (($file = readdir($dh)) !== false) {
83            if (preg_match('/^[\.]/', $file)) continue;
84            if (is_dir($base . '/' . $dir . '/' . $file)) {
85                $dirs[] = $dir . '/' . $file;
86                continue;
87            }
88            if (substr($file, 0, 1) !== '_') continue;
89            $files[] = $dir . '/' . $file;
90        }
91
92        foreach ($files as $file) {
93            //only search txt files
94            if (substr($file, -4) != '.txt') continue;
95            $items[] = array('id' => pathID($file));
96        }
97
98        foreach ($dirs as $sdir) {
99            $items = array_merge($items, $this->getTemplates($base, $sdir, $lvl + 1, $opts));
100        }
101        return $items;
102    }
103
104    protected function printResultHeading() {
105        echo "<h3>".$this->getLang('heading:templates')."</h3>";
106    }
107
108
109    /**
110     * @param string $source
111     * @param string $line
112     *
113     * @return \string[]
114     */
115    public function getDocumentsFromLine($source, $line) {
116        if (trim($line) == '') return array();
117        $cleanline = str_replace('/', ':', $line);
118        $namespace = join(':', explode(':', $cleanline, -1));
119        $documentdir = dirname($this->farm_util->getRemoteFilename($source, $cleanline, null, false));
120
121        $documents = array();
122
123        if (substr($cleanline, -3) == ':**') {
124            $nsfiles = $this->getTemplates($documentdir);
125            $documents = array_map(function ($elem) use ($namespace) {
126                return $namespace . ':' . $elem['id'];
127            }, $nsfiles);
128        } elseif (substr($cleanline, -2) == ':*') {
129            $nsfiles = $this->getTemplates($documentdir, null, null, array('depth' => 1));
130            $documents = array_map(function ($elem) use ($namespace) {
131                return $namespace . ':' . $elem['id'];
132            }, $nsfiles);
133        } else {
134            $document = $cleanline;
135            if (substr(noNS($document), 0, 1) != '_') return array();
136            if (!$this->farm_util->remotePageExists($source, $document, false)) {
137                msg("Template $document does not exist in source wiki!", -1);
138                return array();
139            }
140            $documents[] = $document;
141        }
142        return $documents;
143    }
144}
145