Merge branch '5.5'
[GitHub/WoltLab/com.woltlab.wcf.conversation.git] / files / lib / system / worker / ConversationRebuildDataWorker.class.php
CommitLineData
336dfb29 1<?php
fea86294 2
336dfb29 3namespace wcf\system\worker;
fea86294 4
336dfb29 5use wcf\data\conversation\Conversation;
cb666ba9 6use wcf\data\conversation\ConversationAction;
336dfb29 7use wcf\data\conversation\ConversationEditor;
cb666ba9 8use wcf\data\conversation\ConversationList;
336dfb29
MW
9use wcf\system\WCF;
10
11/**
12 * Worker implementation for updating conversations.
fea86294
TD
13 *
14 * @author Marcel Werk
15 * @copyright 2001-2019 WoltLab GmbH
16 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
fea86294
TD
17 *
18 * @method ConversationList getObjectList()
336dfb29 19 */
fea86294
TD
20class ConversationRebuildDataWorker extends AbstractRebuildDataWorker
21{
22 /**
23 * @inheritDoc
24 */
25 protected $limit = 100;
26
fea86294
TD
27 /**
28 * @inheritDoc
29 */
30 public function countObjects()
31 {
32 if ($this->count === null) {
33 $this->count = 0;
8fbd8b01 34 $sql = "SELECT MAX(conversationID) AS conversationID
bfb64f81
TD
35 FROM wcf1_conversation";
36 $statement = WCF::getDB()->prepare($sql);
fea86294
TD
37 $statement->execute();
38 $row = $statement->fetchArray();
39 if ($row !== false) {
40 $this->count = $row['conversationID'];
41 }
42 }
43 }
44
fea86294
TD
45 /**
46 * @inheritDoc
47 */
48 protected function initObjectList()
49 {
50 $this->objectList = new ConversationList();
51 $this->objectList->sqlOrderBy = 'conversation.conversationID';
52 }
53
54 /**
55 * @inheritDoc
56 */
57 public function execute()
58 {
59 $this->objectList->getConditionBuilder()->add(
60 'conversation.conversationID BETWEEN ? AND ?',
61 [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]
62 );
63
64 parent::execute();
65
66 // prepare statements
8fbd8b01 67 $sql = "SELECT messageID, time, userID, username
bfb64f81 68 FROM wcf1_conversation_message
8fbd8b01
MS
69 WHERE conversationID = ?
70 ORDER BY time";
bfb64f81 71 $firstMessageStatement = WCF::getDB()->prepare($sql, 1);
8fbd8b01 72 $sql = "SELECT time, userID, username
bfb64f81 73 FROM wcf1_conversation_message
8fbd8b01
MS
74 WHERE conversationID = ?
75 ORDER BY time DESC";
bfb64f81 76 $lastMessageStatement = WCF::getDB()->prepare($sql, 1);
8fbd8b01
MS
77 $sql = "SELECT COUNT(*) AS messages,
78 SUM(attachments) AS attachments
bfb64f81 79 FROM wcf1_conversation_message
8fbd8b01 80 WHERE conversationID = ?";
bfb64f81 81 $statsStatement = WCF::getDB()->prepare($sql);
8fbd8b01 82 $sql = "SELECT COUNT(*) AS participants
bfb64f81 83 FROM wcf1_conversation_to_user conversation_to_user
8fbd8b01
MS
84 WHERE conversation_to_user.conversationID = ?
85 AND conversation_to_user.hideConversation <> ?
86 AND conversation_to_user.participantID <> ?
87 AND conversation_to_user.isInvisible = ?";
bfb64f81 88 $participantCounterStatement = WCF::getDB()->prepare($sql);
8fbd8b01 89 $sql = "SELECT conversation_to_user.participantID AS userID, conversation_to_user.hideConversation, user_table.username
bfb64f81
TD
90 FROM wcf1_conversation_to_user conversation_to_user
91 LEFT JOIN wcf1_user user_table
6124508f 92 ON user_table.userID = conversation_to_user.participantID
8fbd8b01
MS
93 WHERE conversation_to_user.conversationID = ?
94 AND conversation_to_user.participantID <> ?
95 AND conversation_to_user.isInvisible = ?
96 ORDER BY user_table.username";
bfb64f81 97 $participantStatement = WCF::getDB()->prepare($sql, 5);
fea86294 98
8fbd8b01 99 $sql = "SELECT COUNT(*) AS participants
bfb64f81 100 FROM wcf1_conversation_to_user
8fbd8b01
MS
101 WHERE conversationID = ?
102 AND hideConversation <> ?
103 AND participantID IS NOT NULL";
bfb64f81 104 $existingParticipantStatement = WCF::getDB()->prepare($sql);
fea86294
TD
105
106 $obsoleteConversations = [];
107 $updateData = [];
108 /** @var Conversation $conversation */
109 foreach ($this->objectList as $conversation) {
230cd7ee
MS
110 // get stats
111 $statsStatement->execute([$conversation->conversationID]);
112 $row = $statsStatement->fetchSingleRow();
fea86294
TD
113
114 // update data
115 $data = [
230cd7ee 116 'attachments' => $row['attachments'] ?: 0,
fea86294
TD
117 'firstMessageID' => $conversation->firstMessageID,
118 'lastPostTime' => $conversation->lastPostTime,
119 'lastPosterID' => $conversation->lastPosterID,
120 'lastPoster' => $conversation->lastPoster,
230cd7ee 121 'replies' => $row['messages'] ? $row['messages'] - 1 : 0,
fea86294
TD
122 'userID' => $conversation->userID,
123 'username' => $conversation->username,
124 ];
125
230cd7ee
MS
126 // check for obsolete conversations
127 $obsolete = $row['messages'] == 0;
128 if (!$obsolete) {
129 if ($conversation->isDraft) {
130 if (!$conversation->userID) {
131 $obsolete = true;
132 }
133 } else {
134 $existingParticipantStatement->execute([$conversation->conversationID, Conversation::STATE_LEFT]);
135 $row = $existingParticipantStatement->fetchSingleRow();
136 if (!$row['participants']) {
137 $obsolete = true;
138 }
139 }
140 }
42795151 141
230cd7ee
MS
142 if ($obsolete) {
143 $obsoleteConversations[] = new ConversationEditor($conversation);
144 continue;
145 }
146
fea86294
TD
147 // get first post
148 $firstMessageStatement->execute([$conversation->conversationID]);
149 if (($row = $firstMessageStatement->fetchSingleRow()) !== false) {
150 $data['firstMessageID'] = $row['messageID'];
151 $data['lastPostTime'] = $data['time'] = $row['time'];
152 $data['userID'] = $row['userID'];
153 $data['username'] = $row['username'];
154 }
155
156 // get last post
157 $lastMessageStatement->execute([$conversation->conversationID]);
158 if (($row = $lastMessageStatement->fetchSingleRow()) !== false) {
159 $data['lastPostTime'] = $row['time'];
160 $data['lastPosterID'] = $row['userID'];
161 $data['lastPoster'] = $row['username'];
162 }
163
fea86294
TD
164 // get number of participants
165 $participantCounterStatement->execute([
166 $conversation->conversationID,
167 Conversation::STATE_LEFT,
168 $conversation->userID,
169 0,
170 ]);
171 $data['participants'] = $participantCounterStatement->fetchSingleColumn();
172
173 // get participant summary
174 $participantStatement->execute([$conversation->conversationID, $conversation->userID, 0]);
175 $users = [];
176 while ($row = $participantStatement->fetchArray()) {
177 $users[] = $row;
178 }
179 $data['participantSummary'] = \serialize($users);
180
181 $updateData[$conversation->conversationID] = $data;
182 }
183
bfb64f81 184 $sql = "UPDATE wcf1_conversation
8fbd8b01
MS
185 SET firstMessageID = ?,
186 lastPostTime = ?,
187 lastPosterID = ?,
188 lastPoster = ?,
189 userID = ?,
190 username = ?,
191 replies = ?,
192 attachments = ?,
193 participants = ?,
194 participantSummary = ?
195 WHERE conversationID = ?";
bfb64f81 196 $statement = WCF::getDB()->prepare($sql);
fea86294
TD
197
198 WCF::getDB()->beginTransaction();
199 foreach ($updateData as $conversationID => $data) {
200 $statement->execute([
201 $data['firstMessageID'],
202 $data['lastPostTime'],
203 $data['lastPosterID'],
204 $data['lastPoster'],
205 $data['userID'],
206 $data['username'],
207 $data['replies'],
208 $data['attachments'],
209 $data['participants'],
210 $data['participantSummary'],
211 $conversationID,
212 ]);
213 }
214 WCF::getDB()->commitTransaction();
215
216 // delete obsolete conversations
217 if (!empty($obsoleteConversations)) {
218 $action = new ConversationAction($obsoleteConversations, 'delete');
219 $action->executeAction();
220 }
221 }
336dfb29 222}