1<?php
2
3namespace dokuwiki\Ui;
4
5use dokuwiki\ChangeLog\ChangeLog;
6
7/**
8 * DokuWiki Diff Interface
9 * parent class of PageDiff and MediaDiff
10 *
11 * @package dokuwiki\Ui
12 */
13abstract class Diff extends Ui
14{
15    /* @var string */
16    protected $id;   // page id or media id
17
18    /* @var int|false */
19    protected $rev1;  // timestamp of older revision
20    /* @var int|false */
21    protected $rev2;  // timestamp of newer revision
22
23    /* @var array */
24    protected $preference = [];
25
26    /* @var ChangeLog */
27    protected $changelog; // PageChangeLog or MediaChangeLog object
28
29    /**
30     * Diff Ui constructor
31     *
32     * @param string $id page id or media id
33     */
34    public function __construct($id)
35    {
36        $this->id = $id;
37        $this->setChangeLog();
38    }
39
40    /**
41     * set class property changelog
42     */
43    abstract protected function setChangeLog();
44
45    /**
46     * Prepare revision info of comparison pair
47     */
48    abstract protected function preProcess();
49
50    /**
51     * Set a pair of revisions to be compared
52     *
53     * @param int $rev1 older revision
54     * @param int $rev2 newer revision
55     * @return $this
56     */
57    public function compare($rev1, $rev2)
58    {
59        if ($rev2 < $rev1) [$rev1, $rev2] = [$rev2, $rev1];
60        $this->rev1 = (int)$rev1;
61        $this->rev2 = (int)$this->changelog->traceCurrentRevision($rev2);
62        return $this;
63    }
64
65    /**
66     * Gets or Sets preference of the Ui\Diff object
67     *
68     * @param string|array $prefs a key name or key-value pair(s)
69     * @param mixed $value value used when the first args is string
70     * @return array|$this
71     */
72    public function preference($prefs = null, $value = null)
73    {
74        // set
75        if (is_string($prefs) && isset($value)) {
76            $this->preference[$prefs] = $value;
77            return $this;
78        } elseif (is_array($prefs)) {
79            foreach ($prefs as $name => $value) {
80                $this->preference[$name] = $value;
81            }
82            return $this;
83        }
84        // get
85        return $this->preference;
86    }
87
88    /**
89     * Handle requested revision(s)
90     *
91     * @return void
92     */
93    protected function handle()
94    {
95        global $INPUT;
96
97        // diff link icon click, eg. &do=diff&rev=#
98        if ($INPUT->has('rev')) {
99            $this->rev1 = $INPUT->int('rev');
100            $this->rev2 = $this->changelog->currentRevision();
101            if ($this->rev2 <= $this->rev1) {
102                // fallback to compare previous with current
103                unset($this->rev1, $this->rev2);
104            }
105        }
106
107        // submit button with two checked boxes, eg. &do=diff&rev2[0]=#&rev2[1]=#
108        $revs = $INPUT->arr('rev2', []);
109        if (count($revs) > 1) {
110            [$rev1, $rev2] = $revs;
111            if ($rev2 < $rev1) [$rev1, $rev2] = [$rev2, $rev1];
112            $this->rev1 = (int)$rev1;
113            $this->rev2 = (int)$this->changelog->traceCurrentRevision($rev2);
114        }
115
116        // no revision was given, compare previous to current
117        if (!isset($this->rev1, $this->rev2)) {
118            $rev2 = $this->changelog->currentRevision();
119            if ($rev2 > $this->changelog->lastRevision()) {
120                $rev1 = $this->changelog->lastRevision();
121            } else {
122                $revs = $this->changelog->getRevisions(0, 1);
123                $rev1 = count($revs) ? $revs[0] : false;
124            }
125            $this->rev1 = $rev1;
126            $this->rev2 = $rev2;
127        }
128    }
129}
130