Use \PDO::fetchAll() instead of PreparedStatement::fetchColumns()
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / edit / EditHistoryManager.class.php
CommitLineData
fb5d4992
TD
1<?php
2namespace wcf\system\edit;
f86d7ff7 3use wcf\data\edit\history\entry\EditHistoryEntryList;
fb5d4992
TD
4use wcf\data\object\type\ObjectTypeCache;
5use wcf\system\exception\SystemException;
6use wcf\system\SingletonFactory;
7use 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
19class 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}