1 | <?php |
||
47 | class MailQueueHandler { |
||
48 | /** Number of entries we want to list in the email */ |
||
49 | const ENTRY_LIMIT = 200; |
||
50 | |||
51 | /** @var array */ |
||
52 | protected $languages; |
||
53 | |||
54 | /** @var string */ |
||
55 | protected $senderAddress; |
||
56 | |||
57 | /** @var string */ |
||
58 | protected $senderName; |
||
59 | |||
60 | /** @var IDateTimeFormatter */ |
||
61 | protected $dateFormatter; |
||
62 | |||
63 | /** @var DataHelper */ |
||
64 | protected $dataHelper; |
||
65 | |||
66 | /** @var IDBConnection */ |
||
67 | protected $connection; |
||
68 | |||
69 | /** @var IMailer */ |
||
70 | protected $mailer; |
||
71 | |||
72 | /** @var IURLGenerator */ |
||
73 | protected $urlGenerator; |
||
74 | |||
75 | /** @var IUserManager */ |
||
76 | protected $userManager; |
||
77 | |||
78 | /** @var IFactory */ |
||
79 | protected $lFactory; |
||
80 | |||
81 | /** @var IManager */ |
||
82 | protected $activityManager; |
||
83 | |||
84 | /** @var LegacyParser */ |
||
85 | protected $legacyParser; |
||
86 | |||
87 | /** |
||
88 | * Constructor |
||
89 | * |
||
90 | * @param IDateTimeFormatter $dateFormatter |
||
91 | * @param IDBConnection $connection |
||
92 | * @param DataHelper $dataHelper |
||
93 | * @param IMailer $mailer |
||
94 | * @param IURLGenerator $urlGenerator |
||
95 | * @param IUserManager $userManager |
||
96 | * @param IFactory $lFactory |
||
97 | * @param IManager $activityManager |
||
98 | * @param LegacyParser $legacyParser |
||
99 | */ |
||
100 | 10 | public function __construct(IDateTimeFormatter $dateFormatter, |
|
119 | |||
120 | /** |
||
121 | * Get the users we want to send an email to |
||
122 | * |
||
123 | * @param int|null $limit |
||
124 | * @param int $latestSend |
||
125 | * @return array |
||
126 | */ |
||
127 | 6 | public function getAffectedUsers($limit, $latestSend) { |
|
128 | 6 | $limit = (!$limit) ? null : (int) $limit; |
|
129 | |||
130 | 6 | $query = $this->connection->prepare( |
|
131 | 'SELECT `amq_affecteduser`, MIN(`amq_latest_send`) AS `amq_trigger_time` ' |
||
132 | . ' FROM `*PREFIX*activity_mq` ' |
||
133 | 6 | . ' WHERE `amq_latest_send` < ? ' |
|
134 | 6 | . ' GROUP BY `amq_affecteduser` ' |
|
135 | 6 | . ' ORDER BY `amq_trigger_time` ASC', |
|
136 | 6 | $limit); |
|
137 | 6 | $query->execute(array($latestSend)); |
|
138 | |||
139 | 6 | $affectedUsers = array(); |
|
140 | 6 | while ($row = $query->fetch()) { |
|
141 | 6 | $affectedUsers[] = $row['amq_affecteduser']; |
|
142 | 6 | } |
|
143 | |||
144 | 6 | return $affectedUsers; |
|
145 | } |
||
146 | |||
147 | /** |
||
148 | * Get all items for the user we want to send an email to |
||
149 | * |
||
150 | * @param string $affectedUser |
||
151 | * @param int $maxTime |
||
152 | * @param int $maxNumItems |
||
153 | * @return array [data of the first max. 200 entries, total number of entries] |
||
154 | */ |
||
155 | 7 | protected function getItemsForUser($affectedUser, $maxTime, $maxNumItems = self::ENTRY_LIMIT) { |
|
156 | 7 | $query = $this->connection->prepare( |
|
157 | 'SELECT * ' |
||
158 | . ' FROM `*PREFIX*activity_mq` ' |
||
159 | 7 | . ' WHERE `amq_timestamp` <= ? ' |
|
160 | 7 | . ' AND `amq_affecteduser` = ? ' |
|
161 | 7 | . ' ORDER BY `amq_timestamp` ASC', |
|
162 | $maxNumItems |
||
163 | 7 | ); |
|
164 | 7 | $query->execute([(int) $maxTime, $affectedUser]); |
|
165 | |||
166 | 7 | $activities = array(); |
|
167 | 7 | while ($row = $query->fetch()) { |
|
168 | 7 | $activities[] = $row; |
|
169 | 7 | } |
|
170 | |||
171 | 7 | if (isset($activities[$maxNumItems - 1])) { |
|
172 | // Reached the limit, run a query to get the actual count. |
||
173 | 1 | $query = $this->connection->prepare( |
|
174 | 'SELECT COUNT(*) AS `actual_count`' |
||
175 | . ' FROM `*PREFIX*activity_mq` ' |
||
176 | 1 | . ' WHERE `amq_timestamp` <= ? ' |
|
177 | 1 | . ' AND `amq_affecteduser` = ?' |
|
178 | 1 | ); |
|
179 | 1 | $query->execute([(int) $maxTime, $affectedUser]); |
|
180 | |||
181 | 1 | $row = $query->fetch(); |
|
182 | 1 | return [$activities, $row['actual_count'] - $maxNumItems]; |
|
183 | } else { |
||
184 | 7 | return [$activities, 0]; |
|
185 | } |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Get a language object for a specific language |
||
190 | * |
||
191 | * @param string $lang Language identifier |
||
192 | * @return \OCP\IL10N Language object of $lang |
||
193 | */ |
||
194 | 1 | protected function getLanguage($lang) { |
|
195 | 1 | if (!isset($this->languages[$lang])) { |
|
196 | 1 | $this->languages[$lang] = $this->lFactory->get('activity', $lang); |
|
197 | 1 | } |
|
198 | |||
199 | 1 | return $this->languages[$lang]; |
|
200 | } |
||
201 | |||
202 | /** |
||
203 | * Get the sender data |
||
204 | * @param string $setting Either `email` or `name` |
||
205 | * @return string |
||
206 | */ |
||
207 | 1 | protected function getSenderData($setting) { |
|
208 | 1 | if (empty($this->senderAddress)) { |
|
209 | 1 | $this->senderAddress = Util::getDefaultEmailAddress('no-reply'); |
|
210 | 1 | } |
|
211 | 1 | if (empty($this->senderName)) { |
|
212 | 1 | $defaults = new Defaults(); |
|
213 | 1 | $this->senderName = $defaults->getName(); |
|
214 | 1 | } |
|
215 | |||
216 | 1 | if ($setting === 'email') { |
|
217 | 1 | return $this->senderAddress; |
|
218 | } |
||
219 | 1 | return $this->senderName; |
|
220 | } |
||
221 | |||
222 | /** |
||
223 | * Send a notification to one user |
||
224 | * |
||
225 | * @param string $userName Username of the recipient |
||
226 | * @param string $email Email address of the recipient |
||
227 | * @param string $lang Selected language of the recipient |
||
228 | * @param string $timezone Selected timezone of the recipient |
||
229 | * @param int $maxTime |
||
230 | * @return bool True if the entries should be removed, false otherwise |
||
231 | */ |
||
232 | 1 | public function sendEmailToUser($userName, $email, $lang, $timezone, $maxTime) { |
|
233 | 1 | $user = $this->userManager->get($userName); |
|
234 | 1 | if (!$user instanceof IUser) { |
|
|
|||
235 | 1 | return true; |
|
236 | } |
||
237 | |||
238 | 1 | list($mailData, $skippedCount) = $this->getItemsForUser($userName, $maxTime); |
|
239 | |||
240 | 1 | $l = $this->getLanguage($lang); |
|
241 | 1 | $this->dataHelper->setUser($userName); |
|
242 | 1 | $this->dataHelper->setL10n($l); |
|
243 | 1 | $this->activityManager->setCurrentUserId($userName); |
|
244 | |||
245 | 1 | $activityList = array(); |
|
246 | 1 | foreach ($mailData as $activity) { |
|
247 | 1 | $event = $this->activityManager->generateEvent(); |
|
248 | 1 | $event->setApp($activity['amq_appid']) |
|
249 | 1 | ->setType($activity['amq_type']) |
|
250 | 1 | ->setTimestamp((int) $activity['amq_timestamp']) |
|
251 | 1 | ->setSubject($activity['amq_subject'], json_decode($activity['amq_subjectparams'], true)); |
|
252 | |||
253 | 1 | $relativeDateTime = $this->dateFormatter->formatDateTimeRelativeDay( |
|
254 | 1 | $activity['amq_timestamp'], |
|
255 | 1 | 'long', 'short', |
|
256 | 1 | new \DateTimeZone($timezone), $l |
|
257 | 1 | ); |
|
258 | |||
259 | try { |
||
260 | 1 | $event = $this->parseEvent($lang, $event); |
|
261 | 1 | } catch (\InvalidArgumentException $e) { |
|
262 | continue; |
||
263 | } |
||
264 | |||
265 | 1 | $activityList[] = array( |
|
266 | 1 | $event->getParsedSubject(), |
|
267 | 1 | $relativeDateTime, |
|
268 | ); |
||
269 | 1 | } |
|
270 | |||
271 | 1 | $alttext = new Template('activity', 'email.notification', '', false); |
|
272 | 1 | $alttext->assign('username', $user->getDisplayName()); |
|
273 | 1 | $alttext->assign('activities', $activityList); |
|
274 | 1 | $alttext->assign('skippedCount', $skippedCount); |
|
275 | 1 | $alttext->assign('installation', $this->urlGenerator->getAbsoluteURL('/')); |
|
276 | 1 | $alttext->assign('overwriteL10N', $l); |
|
277 | 1 | $emailText = $alttext->fetchPage(); |
|
278 | |||
279 | 1 | $message = $this->mailer->createMessage(); |
|
280 | 1 | $message->setTo([$email => $user->getDisplayName()]); |
|
281 | 1 | $message->setSubject((string) $l->t('Activity notification')); |
|
282 | 1 | $message->setPlainBody($emailText); |
|
283 | 1 | $message->setFrom([$this->getSenderData('email') => $this->getSenderData('name')]); |
|
284 | |||
285 | try { |
||
286 | 1 | $this->mailer->send($message); |
|
287 | 1 | } catch (\Exception $e) { |
|
288 | return false; |
||
289 | } |
||
290 | |||
291 | 1 | $this->activityManager->setCurrentUserId(null); |
|
292 | 1 | return true; |
|
293 | } |
||
294 | |||
295 | /** |
||
296 | * @param string $lang |
||
297 | * @param IEvent $event |
||
298 | * @return IEvent |
||
299 | * @throws \InvalidArgumentException when the event could not be parsed |
||
300 | */ |
||
301 | 1 | protected function parseEvent($lang, IEvent $event) { |
|
302 | 1 | foreach ($this->activityManager->getProviders() as $provider) { |
|
303 | try { |
||
304 | $this->activityManager->setFormattingObject($event->getObjectType(), $event->getObjectId()); |
||
305 | $event = $provider->parse($lang, $event); |
||
306 | $this->activityManager->setFormattingObject('', 0); |
||
307 | } catch (\InvalidArgumentException $e) { |
||
308 | } |
||
309 | 1 | } |
|
310 | |||
311 | 1 | if (!$event->getParsedSubject()) { |
|
312 | 1 | $this->activityManager->setFormattingObject($event->getObjectType(), $event->getObjectId()); |
|
313 | 1 | $event = $this->legacyParser->parse($lang, $event); |
|
314 | 1 | $this->activityManager->setFormattingObject('', 0); |
|
315 | 1 | } |
|
316 | |||
317 | 1 | return $event; |
|
318 | } |
||
319 | |||
320 | /** |
||
321 | * Delete all entries we dealt with |
||
322 | * |
||
323 | * @param array $affectedUsers |
||
324 | * @param int $maxTime |
||
325 | */ |
||
326 | 5 | public function deleteSentItems(array $affectedUsers, $maxTime) { |
|
337 | } |
||
338 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.