Commit | Line | Data |
---|---|---|
fb5d4992 TD |
1 | <?php |
2 | namespace wcf\system\edit; | |
f86d7ff7 | 3 | use wcf\data\edit\history\entry\EditHistoryEntryList; |
fb5d4992 TD |
4 | use wcf\data\object\type\ObjectTypeCache; |
5 | use wcf\system\exception\SystemException; | |
6 | use wcf\system\SingletonFactory; | |
7 | use wcf\system\WCF; | |
8 | ||
9 | /** | |
996db334 TD |
10 | * Manages the edit history. |
11 | * | |
12 | * @author Tim Duesterhus | |
2b6cb5c2 | 13 | * @copyright 2001-2015 WoltLab GmbH |
996db334 TD |
14 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
15 | * @package com.woltlab.wcf | |
16 | * @subpackage system.search | |
17 | * @category Community Framework | |
18 | */ | |
fb5d4992 TD |
19 | class EditHistoryManager extends SingletonFactory { |
20 | /** | |
996db334 TD |
21 | * list of available object types |
22 | * @var array | |
23 | */ | |
fb5d4992 TD |
24 | protected $availableObjectTypes = array(); |
25 | ||
26 | /** | |
996db334 TD |
27 | * @see \wcf\system\SingletonFactory::init() |
28 | */ | |
fb5d4992 TD |
29 | protected function init() { |
30 | // get available object types | |
31 | $this->availableObjectTypes = ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.edit.historySavingObject'); | |
32 | } | |
33 | ||
34 | /** | |
996db334 TD |
35 | * Returns the id of the object type with the given name. |
36 | * | |
37 | * @param string $objectType | |
38 | * @return integer | |
2b770bdd | 39 | * @throws SystemException |
996db334 | 40 | */ |
fb5d4992 TD |
41 | public function getObjectTypeID($objectType) { |
42 | if (!isset($this->availableObjectTypes[$objectType])) { | |
43 | throw new SystemException("unknown object type '".$objectType."'"); | |
44 | } | |
45 | ||
46 | return $this->availableObjectTypes[$objectType]->objectTypeID; | |
47 | } | |
48 | ||
49 | /** | |
996db334 TD |
50 | * Adds a new entry. |
51 | * | |
52 | * @param string $objectType | |
53 | * @param integer $objectID | |
54 | * @param string $message | |
55 | * @param integer $time | |
56 | * @param integer $userID | |
57 | * @param string $username | |
58 | * @param string $editReason | |
f86d7ff7 | 59 | * @param integer $obsoletedByUserID The userID of the user that forced this entry to become outdated |
996db334 | 60 | */ |
f86d7ff7 | 61 | public function add($objectType, $objectID, $message, $time, $userID, $username, $editReason, $obsoletedByUserID) { |
77838209 TD |
62 | // no op, if edit history is disabled |
63 | if (!MODULE_EDIT_HISTORY) return; | |
64 | ||
fb5d4992 TD |
65 | // save new entry |
66 | $sql = "INSERT INTO wcf".WCF_N."_edit_history_entry | |
f86d7ff7 TD |
67 | (objectTypeID, objectID, message, time, obsoletedAt, userID, username, editReason, obsoletedByUserID) |
68 | VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; | |
fb5d4992 | 69 | $statement = WCF::getDB()->prepareStatement($sql); |
f86d7ff7 | 70 | $statement->execute(array($this->getObjectTypeID($objectType), $objectID, $message, $time, TIME_NOW, $userID, $username, $editReason, $obsoletedByUserID)); |
fb5d4992 | 71 | } |
6a248739 TD |
72 | |
73 | /** | |
996db334 TD |
74 | * Deletes edit history entries. |
75 | * | |
76 | * @param string $objectType | |
7a23a706 | 77 | * @param integer[] $objectIDs |
996db334 | 78 | */ |
6a248739 TD |
79 | public function delete($objectType, array $objectIDs) { |
80 | $objectTypeID = $this->getObjectTypeID($objectType); | |
81 | ||
82 | $sql = "DELETE FROM wcf".WCF_N."_edit_history_entry | |
83 | WHERE objectTypeID = ? | |
84 | AND objectID = ?"; | |
85 | $statement = WCF::getDB()->prepareStatement($sql); | |
86 | WCF::getDB()->beginTransaction(); | |
87 | foreach ($objectIDs as $objectID) { | |
88 | $statement->execute(array($objectTypeID, $objectID)); | |
89 | } | |
90 | WCF::getDB()->commitTransaction(); | |
91 | } | |
f86d7ff7 TD |
92 | |
93 | /** | |
94 | * Performs mass reverting of edits by the given users in the given timeframe. | |
95 | * | |
7a23a706 | 96 | * @param integer[] $userIDs |
f86d7ff7 TD |
97 | * @param integer $timeframe |
98 | */ | |
99 | public function bulkRevert(array $userIDs, $timeframe = 86400) { | |
100 | if (empty($userIDs)) return; | |
101 | ||
102 | // 1: Select the newest edit history item for each object ("newestEntries") | |
103 | // 2: Check whether the edit was made by the offending users ("vandalizedEntries") | |
104 | // 3: Fetch the newest version that is either: | |
105 | // a) older than $timeframe days | |
106 | // b) by a non offending user | |
107 | $userIDPlaceholders = '?'.str_repeat(',?', count($userIDs) - 1); | |
108 | $sql = "SELECT MAX(entryID) | |
109 | FROM wcf".WCF_N."_edit_history_entry revertTo | |
110 | INNER JOIN( | |
111 | SELECT vandalizedEntries.objectID, | |
112 | vandalizedEntries.objectTypeID | |
113 | FROM wcf".WCF_N."_edit_history_entry vandalizedEntries | |
114 | INNER JOIN ( | |
115 | SELECT MAX(newestEntries.entryID) AS entryID | |
116 | FROM wcf".WCF_N."_edit_history_entry newestEntries | |
117 | WHERE newestEntries.obsoletedAt > ? | |
118 | GROUP BY newestEntries.objectTypeID, newestEntries.objectID | |
119 | ) newestEntries2 | |
120 | WHERE newestEntries2.entryID = vandalizedEntries.entryID | |
121 | AND vandalizedEntries.obsoletedByUserID IN (".$userIDPlaceholders.") | |
122 | ) AS vandalizedEntries2 | |
123 | WHERE revertTo.objectID = vandalizedEntries2.objectID | |
124 | AND revertTo.objectTypeID = vandalizedEntries2.objectTypeID | |
125 | AND ( revertTo.obsoletedAt <= ? | |
126 | OR revertTo.userID NOT IN(".$userIDPlaceholders.")) | |
127 | GROUP BY revertTo.objectTypeID, revertTo.objectID"; | |
128 | $statement = WCF::getDB()->prepareStatement($sql); | |
129 | $statement->execute(array_merge( | |
130 | array(TIME_NOW - $timeframe), | |
131 | $userIDs, | |
132 | array(TIME_NOW - $timeframe), | |
133 | $userIDs | |
134 | )); | |
135 | ||
cd975610 | 136 | $entryIDs = $statement->fetchAll(\PDO::FETCH_COLUMN); |
f86d7ff7 TD |
137 | if (empty($entryIDs)) return; |
138 | ||
139 | $list = new EditHistoryEntryList(); | |
140 | $list->getConditionBuilder()->add('entryID IN(?)', array($entryIDs)); | |
141 | $list->readObjects(); | |
142 | foreach ($list as $entry) { | |
143 | $entry->getObject()->revertVersion($entry); | |
144 | } | |
145 | } | |
fb5d4992 | 146 | } |