Commit | Line | Data |
---|---|---|
c1c06a6a TD |
1 | <?php |
2 | namespace wcf\page; | |
3 | use wcf\data\edit\history\entry\EditHistoryEntry; | |
5e40b0b2 | 4 | use wcf\data\edit\history\entry\EditHistoryEntryList; |
849204bd | 5 | use wcf\data\object\type\ObjectType; |
c1c06a6a | 6 | use wcf\data\object\type\ObjectTypeCache; |
2c04b6a9 | 7 | use wcf\data\DatabaseObjectList; |
849204bd | 8 | use wcf\system\edit\IHistorySavingObject; |
e4499881 | 9 | use wcf\system\edit\IHistorySavingObjectTypeProvider; |
c1c06a6a | 10 | use wcf\system\exception\IllegalLinkException; |
4b3690e1 | 11 | use wcf\system\request\LinkHandler; |
c1c06a6a TD |
12 | use wcf\system\WCF; |
13 | use wcf\util\Diff; | |
4b3690e1 | 14 | use wcf\util\HeaderUtil; |
c1c06a6a TD |
15 | use wcf\util\StringUtil; |
16 | ||
17 | /** | |
18 | * Compares two templates. | |
19 | * | |
20 | * @author Tim Duesterhus | |
c839bd49 | 21 | * @copyright 2001-2018 WoltLab GmbH |
c1c06a6a | 22 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
e71525e4 | 23 | * @package WoltLabSuite\Core\Page |
c1c06a6a TD |
24 | */ |
25 | class EditHistoryPage extends AbstractPage { | |
77838209 | 26 | /** |
849204bd | 27 | * @inheritDoc |
77838209 | 28 | */ |
849204bd | 29 | public $neededModules = ['MODULE_EDIT_HISTORY']; |
77838209 | 30 | |
5e40b0b2 TD |
31 | /** |
32 | * DatabaseObjectList object | |
849204bd | 33 | * @var DatabaseObjectList |
5e40b0b2 | 34 | */ |
849204bd | 35 | public $objectList; |
1a6e8c52 | 36 | |
c1c06a6a TD |
37 | /** |
38 | * left / old version id | |
39 | * @var integer | |
40 | */ | |
41 | public $oldID = 0; | |
42 | ||
43 | /** | |
44 | * left / old version | |
849204bd | 45 | * @var EditHistoryEntry |
c1c06a6a | 46 | */ |
849204bd | 47 | public $old; |
c1c06a6a TD |
48 | |
49 | /** | |
50 | * right / new version id | |
51 | * @var integer | |
52 | */ | |
53 | public $newID = 0; | |
54 | ||
55 | /** | |
56 | * right / new version | |
849204bd | 57 | * @var EditHistoryEntry |
c1c06a6a | 58 | */ |
849204bd | 59 | public $new; |
c1c06a6a TD |
60 | |
61 | /** | |
62 | * differences between both versions | |
849204bd | 63 | * @var Diff |
c1c06a6a | 64 | */ |
849204bd | 65 | public $diff; |
c1c06a6a | 66 | |
c1c06a6a TD |
67 | /** |
68 | * object type of the requested object | |
849204bd | 69 | * @var ObjectType |
c1c06a6a | 70 | */ |
849204bd | 71 | public $objectType; |
c1c06a6a TD |
72 | |
73 | /** | |
74 | * id of the requested object | |
75 | * @var integer | |
76 | */ | |
77 | public $objectID = 0; | |
78 | ||
79 | /** | |
80 | * requested object | |
849204bd | 81 | * @var IHistorySavingObject |
c1c06a6a | 82 | */ |
849204bd | 83 | public $object; |
c1c06a6a TD |
84 | |
85 | /** | |
849204bd | 86 | * @inheritDoc |
5e40b0b2 | 87 | */ |
c1c06a6a TD |
88 | public function readParameters() { |
89 | parent::readParameters(); | |
90 | ||
ca1f89cf | 91 | if (isset($_REQUEST['oldID'])) { |
c1c06a6a TD |
92 | $this->oldID = intval($_REQUEST['oldID']); |
93 | $this->old = new EditHistoryEntry($this->oldID); | |
94 | if (!$this->old->entryID) throw new IllegalLinkException(); | |
95 | ||
ca1f89cf | 96 | if (isset($_REQUEST['newID']) && $_REQUEST['newID'] !== 'current') { |
c1c06a6a TD |
97 | $this->newID = intval($_REQUEST['newID']); |
98 | $this->new = new EditHistoryEntry($this->newID); | |
99 | if (!$this->new->entryID) throw new IllegalLinkException(); | |
100 | } | |
101 | ||
102 | // if new version isn't 'current' check whether they are comparable | |
103 | if ($this->new) { | |
104 | // different objectTypes cannot be compared | |
105 | if ($this->old->objectTypeID != $this->new->objectTypeID) throw new IllegalLinkException(); | |
106 | // different items cannot be compared | |
107 | if ($this->old->objectID != $this->new->objectID) throw new IllegalLinkException(); | |
108 | } | |
109 | ||
110 | $this->objectID = $this->old->objectID; | |
812915cc | 111 | $this->objectType = ObjectTypeCache::getInstance()->getObjectType($this->old->objectTypeID); |
c1c06a6a | 112 | } |
812915cc | 113 | else if (isset($_REQUEST['objectID']) && isset($_REQUEST['objectType'])) { |
c1c06a6a | 114 | $this->objectID = intval($_REQUEST['objectID']); |
812915cc | 115 | $this->objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.edit.historySavingObject', $_REQUEST['objectType']); |
c1c06a6a TD |
116 | } |
117 | else { | |
118 | throw new IllegalLinkException(); | |
119 | } | |
120 | ||
c4a4a442 | 121 | if (!$this->objectType) throw new IllegalLinkException(); |
e4499881 MS |
122 | |
123 | /** @var IHistorySavingObjectTypeProvider $processor */ | |
c1c06a6a | 124 | $processor = $this->objectType->getProcessor(); |
e4499881 MS |
125 | |
126 | /** @var IHistorySavingObject object */ | |
c1c06a6a | 127 | $this->object = $processor->getObjectByID($this->objectID); |
f9c4a0ba | 128 | if (!$this->object->getObjectID()) throw new IllegalLinkException(); |
c1c06a6a | 129 | $processor->checkPermissions($this->object); |
849204bd | 130 | $this->object->setLocation(); |
c1c06a6a | 131 | |
c4a4a442 | 132 | if (isset($_REQUEST['newID']) && !$this->new) { |
c1c06a6a | 133 | $this->new = $this->object; |
519200eb | 134 | $this->newID = 'current'; |
c1c06a6a | 135 | } |
4b3690e1 MW |
136 | |
137 | if (!empty($_POST)) { | |
849204bd | 138 | HeaderUtil::redirect(LinkHandler::getInstance()->getLink('EditHistory', [ |
4b3690e1 MW |
139 | 'objectID' => $this->objectID, |
140 | 'objectType' => $this->objectType->objectType, | |
141 | 'newID' => $this->newID, | |
142 | 'oldID' => $this->oldID | |
849204bd | 143 | ])); |
4b3690e1 MW |
144 | exit; |
145 | } | |
c1c06a6a TD |
146 | } |
147 | ||
148 | /** | |
849204bd | 149 | * @inheritDoc |
996db334 | 150 | */ |
c1c06a6a TD |
151 | public function readData() { |
152 | parent::readData(); | |
153 | ||
5e40b0b2 | 154 | $this->objectList = new EditHistoryEntryList(); |
fd1a6431 | 155 | $this->objectList->sqlOrderBy = "time DESC, entryID DESC"; |
849204bd AE |
156 | $this->objectList->getConditionBuilder()->add('objectTypeID = ?', [$this->objectType->objectTypeID]); |
157 | $this->objectList->getConditionBuilder()->add('objectID = ?', [$this->objectID]); | |
5e40b0b2 TD |
158 | $this->objectList->readObjects(); |
159 | ||
c1c06a6a | 160 | // valid IDs were given, calculate diff |
ca1f89cf | 161 | if ($this->old && $this->new) { |
b32308d4 TD |
162 | $a = explode("\n", StringUtil::unifyNewlines(StringUtil::trim($this->old->getMessage()))); |
163 | $b = explode("\n", StringUtil::unifyNewlines(StringUtil::trim($this->new->getMessage()))); | |
948b2593 TD |
164 | $diff = new Diff($a, $b); |
165 | $this->diff = $diff->getRawDiff(); | |
166 | ||
167 | // create word diff for small changes (only one consecutive paragraph modified) | |
168 | for ($i = 0, $max = count($this->diff); $i < $max;) { | |
169 | $previousIsNotRemoved = !isset($this->diff[$i - 1][0]) || $this->diff[$i - 1][0] !== Diff::REMOVED; | |
170 | $currentIsRemoved = $this->diff[$i][0] === Diff::REMOVED; | |
171 | $nextIsAdded = isset($this->diff[$i + 1][0]) && $this->diff[$i + 1][0] === Diff::ADDED; | |
172 | $afterNextIsNotAdded = !isset($this->diff[$i + 2][0]) || $this->diff[$i + 2][0] !== Diff::ADDED; | |
173 | ||
174 | if ($previousIsNotRemoved && $currentIsRemoved && $nextIsAdded && $afterNextIsNotAdded) { | |
175 | $a = preg_split('/(\\W)/u', $this->diff[$i][1], -1, PREG_SPLIT_DELIM_CAPTURE); | |
176 | $b = preg_split('/(\\W)/u', $this->diff[$i + 1][1], -1, PREG_SPLIT_DELIM_CAPTURE); | |
177 | ||
178 | $diff = new Diff($a, $b); | |
179 | $this->diff[$i][1] = ''; | |
180 | $this->diff[$i + 1][1] = ''; | |
181 | foreach ($diff->getRawDiff() as $entry) { | |
182 | $entry[1] = StringUtil::encodeHTML($entry[1]); | |
183 | ||
184 | if ($entry[0] === Diff::SAME) { | |
185 | $this->diff[$i][1] .= $entry[1]; | |
186 | $this->diff[$i + 1][1] .= $entry[1]; | |
187 | } | |
188 | else if ($entry[0] === Diff::REMOVED) { | |
189 | $this->diff[$i][1] .= '<strong>'.$entry[1].'</strong>'; | |
190 | } | |
191 | else if ($entry[0] === Diff::ADDED) { | |
192 | $this->diff[$i + 1][1] .= '<strong>'.$entry[1].'</strong>'; | |
193 | } | |
194 | } | |
195 | $i += 2; | |
196 | } | |
197 | else { | |
198 | $this->diff[$i][1] = StringUtil::encodeHTML($this->diff[$i][1]); | |
199 | $i++; | |
200 | } | |
201 | } | |
c1c06a6a | 202 | } |
4a89a7d1 MW |
203 | |
204 | // set default values | |
205 | if (!isset($_REQUEST['oldID']) && !isset($_REQUEST['newID'])) { | |
206 | foreach ($this->objectList as $object) { | |
207 | $this->oldID = $object->entryID; | |
208 | break; | |
209 | } | |
210 | $this->newID = 'current'; | |
211 | } | |
c1c06a6a TD |
212 | } |
213 | ||
214 | /** | |
849204bd | 215 | * @inheritDoc |
996db334 | 216 | */ |
c1c06a6a TD |
217 | public function assignVariables() { |
218 | parent::assignVariables(); | |
219 | ||
849204bd | 220 | WCF::getTPL()->assign([ |
c1c06a6a TD |
221 | 'oldID' => $this->oldID, |
222 | 'old' => $this->old, | |
223 | 'newID' => $this->newID, | |
224 | 'new' => $this->new, | |
225 | 'object' => $this->object, | |
5e40b0b2 | 226 | 'diff' => $this->diff, |
812915cc TD |
227 | 'objects' => $this->objectList, |
228 | 'objectID' => $this->objectID, | |
229 | 'objectType' => $this->objectType | |
849204bd | 230 | ]); |
c1c06a6a TD |
231 | } |
232 | } |