This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace ST; |
||
4 | |||
5 | use Content; |
||
6 | use ContentHandler; |
||
7 | use Exception; |
||
8 | use IContextSource; |
||
9 | use Language; |
||
10 | use MediaWiki\Diff\ComplexityException; |
||
11 | use MWException; |
||
12 | use ParserOutput; |
||
13 | use SMW\ApplicationFactory; |
||
14 | use SMW\DIWikiPage; |
||
15 | use SMWDataItem; |
||
16 | use SMWPrintRequest; |
||
17 | use Title; |
||
18 | use User; |
||
19 | use WikiPage; |
||
20 | |||
21 | if ( !defined( 'MEDIAWIKI' ) ) { |
||
22 | echo 'Not a valid entry point'; |
||
23 | exit( 1 ); |
||
24 | } |
||
25 | |||
26 | if ( !defined( 'SMW_VERSION' ) ) { |
||
27 | echo 'This extension requires Semantic MediaWiki to be installed.'; |
||
28 | exit( 1 ); |
||
29 | } |
||
30 | |||
31 | // constants for message type |
||
32 | if ( !defined( 'ST_NEWTASK' ) ) { |
||
33 | define( 'ST_NEWTASK', 0 ); |
||
34 | define( 'ST_UPDATE', 1 ); |
||
35 | define( 'ST_ASSIGNED', 2 ); |
||
36 | define( 'ST_CLOSED', 3 ); |
||
37 | define( 'ST_UNASSIGNED', 4 ); |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * This class handles the creation and sending of notification emails. |
||
42 | */ |
||
43 | class SemanticTasksMailer { |
||
44 | |||
45 | private static $user_mailer; |
||
46 | |||
47 | /** |
||
48 | * Mails the assignees when the task is modified |
||
49 | * |
||
50 | * @param Assignees $assignees |
||
51 | * @param WikiPage $article |
||
52 | * @param User $current_user |
||
53 | * @param Content $text |
||
54 | * @param string $summary Unused |
||
55 | * @param bool $minoredit |
||
56 | * @param null $watchthis Unused |
||
57 | * @param null $sectionanchor Unused |
||
58 | * @param $flags |
||
59 | * @return boolean |
||
60 | * @throws ComplexityException |
||
61 | * @throws MWException |
||
62 | */ |
||
63 | public static function mailAssigneesUpdatedTask( Assignees $assignees, WikiPage $article, User $current_user, $text, |
||
64 | $summary, $minoredit, $watchthis, $sectionanchor, $flags, $revision ) { |
||
0 ignored issues
–
show
|
|||
65 | if ( $minoredit ) { |
||
66 | return true; |
||
67 | } |
||
68 | $status = ST_UPDATE; |
||
69 | if ( ( $flags & EDIT_NEW ) && !$article->getTitle()->isTalkPage() ) { |
||
70 | $status = ST_NEWTASK; |
||
71 | } |
||
72 | |||
73 | return self::mailAssignees( $article, $text, $current_user, $status, $assignees, $revision ); |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * |
||
78 | * @param WikiPage $article |
||
79 | * @param Content $content |
||
80 | * @param User $user |
||
81 | * @param integer $status |
||
82 | * @param Assignees $assignees |
||
83 | * @return boolean |
||
84 | * @throws ComplexityException |
||
85 | * @throws MWException |
||
86 | * @global boolean $wgSemanticTasksNotifyIfUnassigned |
||
87 | */ |
||
88 | static function mailAssignees( WikiPage $article, Content $content, User $user, $status, Assignees $assignees, |
||
0 ignored issues
–
show
|
|||
89 | $revision ) { |
||
90 | $text = ContentHandler::getContentText( $content ); |
||
91 | $title = $article->getTitle(); |
||
92 | |||
93 | // Notify those unassigned from this task |
||
94 | global $wgSemanticTasksNotifyIfUnassigned; |
||
95 | if ( $wgSemanticTasksNotifyIfUnassigned ) { |
||
96 | $removedAssignees = $assignees->getRemovedAssignees( $article, $revision ); |
||
97 | $removedAssignees = Assignees::getAssigneeAddresses( $removedAssignees ); |
||
98 | self::mailNotification( $removedAssignees, $text, $title, $user, ST_UNASSIGNED ); |
||
99 | } |
||
100 | |||
101 | // Send notification of an assigned task to assignees |
||
102 | // Treat task as new |
||
103 | $newAssignees = $assignees->getNewAssignees( $article, $revision ); |
||
104 | $newAssignees = Assignees::getAssigneeAddresses( $newAssignees ); |
||
105 | self::mailNotification( $newAssignees, $text, $title, $user, ST_ASSIGNED ); |
||
106 | |||
107 | $copies = $assignees->getCurrentCarbonCopy( $article, $revision ); |
||
108 | $currentStatus = $assignees->getCurrentStatus( $article, $revision ); |
||
109 | $oldStatus = $assignees->getSavedStatus(); |
||
110 | if ( $currentStatus === "Closed" && $oldStatus !== "Closed" ) { |
||
111 | $close_mailto = Assignees::getAssigneeAddresses( $copies ); |
||
112 | self::mailNotification( $close_mailto, $text, $title, $user, ST_CLOSED ); |
||
113 | } |
||
114 | |||
115 | $currentAssignees = $assignees->getCurrentAssignees( $article, $revision ); |
||
116 | |||
117 | // Only send group notifications on new tasks |
||
118 | $groups = array(); |
||
119 | if ( $status === ST_NEWTASK ) { |
||
120 | $groups = $assignees->getGroupAssignees( $article ); |
||
121 | } |
||
122 | |||
123 | $mailto = array_merge( $currentAssignees, $copies, $groups ); |
||
124 | $mailto = array_unique( $mailto ); |
||
125 | $mailto = Assignees::getAssigneeAddresses( $mailto ); |
||
126 | |||
127 | // Send notifications to assignees, ccs, and groups |
||
128 | self::mailNotification( $mailto, $text, $title, $user, $status ); |
||
129 | |||
130 | return true; |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * Sends mail notifications |
||
135 | * |
||
136 | * @param array $assignees |
||
137 | * @param string $text |
||
138 | * @param Title $title |
||
139 | * @param User $user |
||
140 | * @param integer $status |
||
141 | * @throws MWException |
||
142 | * @throws ComplexityException |
||
143 | * @global string $wgSitename |
||
144 | */ |
||
145 | static function mailNotification( array $assignees, $text, Title $title, User $user, $status ) { |
||
0 ignored issues
–
show
|
|||
146 | global $wgSitename; |
||
147 | |||
148 | if ( empty( $assignees ) ) { |
||
149 | return; |
||
150 | } |
||
151 | $title_text = $title->getFullText(); |
||
152 | $from = new \MailAddress( $user->getEmail(), $user->getName() ); |
||
153 | $link = htmlspecialchars( $title->getFullURL() ); |
||
154 | |||
155 | /** @todo This should probably be refactored */ |
||
156 | if ( $status == ST_NEWTASK ) { |
||
157 | $subject = '[' . $wgSitename . '] ' . wfMessage( 'semantictasks-newtask' )->text() . ' ' . |
||
158 | $title_text; |
||
159 | $message = 'semantictasks-newtask-msg'; |
||
160 | $body = wfMessage( $message, $title_text )->text() . " " . $link; |
||
161 | $body .= "\n \n" . wfMessage( 'semantictasks-text-message' )->text() . "\n" . $text; |
||
162 | } elseif ( $status == ST_UPDATE ) { |
||
163 | $subject = '[' . $wgSitename . '] ' . wfMessage( 'semantictasks-taskupdated' )->text() . ' ' . |
||
164 | $title_text; |
||
165 | $message = 'semantictasks-updatedtoyou-msg2'; |
||
166 | $body = wfMessage( $message, $title_text )->text() . " " . $link; |
||
167 | $body .= "\n \n" . wfMessage( 'semantictasks-diff-message' )->text() . "\n" . |
||
168 | self::generateDiffBodyTxt( $title ); |
||
169 | } elseif ( $status == ST_CLOSED ) { |
||
170 | $subject = '[' . $wgSitename . '] ' . wfMessage( 'semantictasks-taskclosed' )->text() . ' ' . |
||
171 | $title_text; |
||
172 | $message = 'semantictasks-taskclosed-msg'; |
||
173 | $body = wfMessage( $message, $title_text )->text() . " " . $link; |
||
174 | $body .= "\n \n" . wfMessage( 'semantictasks-text-message' )->text() . "\n" . $text; |
||
175 | } elseif ( $status == ST_UNASSIGNED ) { |
||
176 | $subject = '[' . $wgSitename . '] ' . wfMessage( 'semantictasks-taskunassigned' )->text() . ' ' . |
||
177 | $title_text; |
||
178 | $message = 'semantictasks-unassignedtoyou-msg2'; |
||
179 | $body = wfMessage( $message, $title_text )->text() . " " . $link; |
||
180 | $body .= "\n \n" . wfMessage( 'semantictasks-text-message' )->text() . "\n" . $text; |
||
181 | } else { |
||
182 | // status == ASSIGNED |
||
183 | $subject = '[' . $wgSitename . '] ' . wfMessage( 'semantictasks-taskassigned' )->text() . ' ' . |
||
184 | $title_text; |
||
185 | $message = 'semantictasks-assignedtoyou-msg2'; |
||
186 | $body = wfMessage( $message, $title_text )->text() . " " . $link; |
||
187 | $body .= "\n \n" . wfMessage( 'semantictasks-text-message' )->text() . "\n" . $text; |
||
188 | } |
||
189 | |||
190 | if (!self::$user_mailer) { |
||
191 | self::$user_mailer = new \ST\UserMailer(new \UserMailer()); |
||
192 | } |
||
193 | |||
194 | self::$user_mailer->send( $assignees, $from, $subject, $body ); |
||
195 | } |
||
196 | |||
197 | static function setUserMailer(\ST\UserMailer $user_mailer) { |
||
0 ignored issues
–
show
|
|||
198 | self::$user_mailer = $user_mailer; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Generates a diff txt |
||
203 | * |
||
204 | * Code is similar to DifferenceEngine::generateTextDiffBody |
||
205 | * @param Title $title |
||
206 | * @param IContextSource $context |
||
207 | * @return string |
||
208 | * @throws ComplexityException |
||
209 | * @throws MWException |
||
210 | */ |
||
211 | static function generateDiffBodyTxt( Title $title, IContextSource $context = null) { |
||
0 ignored issues
–
show
|
|||
212 | $revision = \Revision::newFromTitle( $title, 0 ); |
||
213 | if ($revision === null) { |
||
214 | return ''; |
||
215 | } |
||
216 | /** @todo The first parameter should be a Context. */ |
||
217 | $diff = new \DifferenceEngine( $context, $revision->getId(), 'prev' ); |
||
218 | // The DifferenceEngine::getDiffBody() method generates html, |
||
219 | // so let's generate the txt diff manually: |
||
220 | global $wgContLang; |
||
221 | $diff->loadText(); |
||
222 | $otext = ''; |
||
223 | $ntext = ''; |
||
224 | if ( version_compare( MW_VERSION, '1.32', '<' ) ) { |
||
225 | $otext = str_replace( "\r\n", "\n", \ContentHandler::getContentText( $diff->mOldContent ) ); |
||
226 | $ntext = str_replace( "\r\n", "\n", \ContentHandler::getContentText( $diff->mNewContent ) ); |
||
227 | } else { |
||
228 | if ($diff->getOldRevision()) { |
||
229 | $otext = str_replace( "\r\n", "\n", ContentHandler::getContentText( $diff->getOldRevision()->getContent( 'main' ) ) ); |
||
230 | } |
||
231 | if ($diff->getNewRevision()) { |
||
232 | $ntext = str_replace( "\r\n", "\n", ContentHandler::getContentText( $diff->getNewRevision()->getContent( 'main' ) ) ); |
||
233 | } |
||
234 | } |
||
235 | $ota = explode( "\n", $wgContLang->segmentForDiff( $otext ) ); |
||
236 | $nta = explode( "\n", $wgContLang->segmentForDiff( $ntext ) ); |
||
237 | // We use here the php diff engine included in MediaWiki |
||
238 | $diffs = new \Diff( $ota, $nta ); |
||
239 | // And we ask for a txt formatted diff |
||
240 | $formatter = new \UnifiedDiffFormatter(); |
||
241 | $diff_text = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ); |
||
242 | return $diff_text; |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Run by the maintenance script to remind the assignees |
||
247 | * |
||
248 | * @return boolean |
||
249 | * @throws Exception |
||
250 | * @global string $wgSitename |
||
251 | * @global Language $wgLang |
||
252 | */ |
||
253 | static function remindAssignees() { |
||
254 | global $wgSitename; |
||
255 | global $stgPropertyReminderAt; |
||
256 | global $stgPropertyAssignedTo; |
||
257 | global $stgPropertyTargetDate; |
||
258 | global $stgPropertyStatus; |
||
259 | |||
260 | # Make this equal to midnight. Rational is that if users set today as the Target date with |
||
261 | # reminders set to "0" so that the reminder happens on the deadline, the reminders will go |
||
262 | # out even though now it is after the beginning of today and technically past the |
||
263 | # target date. |
||
264 | $today = wfTimestamp( TS_ISO_8601, strtotime( 'today midnight' ) ); |
||
265 | |||
266 | # Get tasks where a reminder is called for, whose status is either new or in progress, and |
||
267 | # whose target date is in the future. |
||
268 | $query_string = "[[$stgPropertyReminderAt::+]][[$stgPropertyStatus::New||In Progress]][[$stgPropertyTargetDate::≥ $today]]"; |
||
269 | $properties_to_display = array( $stgPropertyReminderAt, $stgPropertyAssignedTo, $stgPropertyTargetDate ); |
||
270 | |||
271 | $results = Query::getQueryResults( $query_string, $properties_to_display, true ); |
||
272 | if ( empty( $results ) ) { |
||
273 | return false; |
||
274 | } |
||
275 | |||
276 | while ( $row = $results->getNext() ) { |
||
277 | $task_name = $row[0]->getNextObject()->getTitle(); |
||
278 | $subject = '[' . $wgSitename . '] ' . wfMessage( 'semantictasks-reminder' )->text() . $task_name; |
||
279 | // The following doesn't work, maybe because we use a cron job. |
||
280 | // $link = $task_name->getFullURL(); |
||
281 | // So let's do it manually |
||
282 | //$link = $wiki_url . $task_name->getPartialURL(); |
||
283 | // You know what? Let's try it again. |
||
284 | $link = $task_name->getFullURL(); |
||
285 | |||
286 | $target_date = $row[3]->getNextObject(); |
||
287 | $tg_date = new DateTime( $target_date->getShortHTMLText() ); |
||
288 | |||
289 | while ( $reminder = $row[1]->getNextObject() ) { |
||
290 | $remind_me_in = $reminder->getShortHTMLText(); |
||
291 | $date = new DateTime( 'today midnight' ); |
||
292 | $date->modify( "+$remind_me_in day" ); |
||
293 | |||
294 | if ( $tg_date === $date ) { |
||
295 | global $wgLang; |
||
296 | while ( $task_assignee = $row[2]->getNextObject() ) { |
||
297 | $assignee_username = $task_assignee->getTitle()->getText(); |
||
298 | $assignee = User::newFromName( $assignee_username ); |
||
299 | |||
300 | $body = wfMessage( 'semantictasks-reminder-message2', $task_name, |
||
301 | $wgLang->formatNum( $remind_me_in ), $link )->text(); |
||
302 | $assignee->sendMail( $subject, $body ); |
||
303 | } |
||
304 | } |
||
305 | } |
||
306 | } |
||
307 | return true; |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * Prints debugging information. $debugText is what you want to print, $debugVal |
||
312 | * is the level at which you want to print the information. |
||
313 | * |
||
314 | * @global boolean $wgSemanticTasksDebug |
||
315 | * @param string $debugText |
||
316 | * @param string $debugArr |
||
317 | * @access private |
||
318 | */ |
||
319 | static function printDebug( $debugText, $debugArr = null ) { |
||
320 | global $wgSemanticTasksDebug; |
||
321 | |||
322 | if ( $wgSemanticTasksDebug ) { |
||
323 | if ( isset( $debugArr ) ) { |
||
324 | $text = $debugText . ' ' . implode( '::', $debugArr ); |
||
325 | wfDebugLog( 'semantic-tasks', $text, false ); |
||
326 | } else { |
||
327 | wfDebugLog( 'semantic-tasks', $debugText, false ); |
||
328 | } |
||
329 | } |
||
330 | } |
||
331 | |||
332 | } |
||
333 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.